mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
428 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 168d96a182 | |||
| 2075761282 | |||
| d59de1f158 | |||
| d64716ab74 | |||
| 0ffbb8c364 | |||
| c29960abf2 | |||
| 315cb24046 | |||
| 4cabc5684b | |||
| 256c9be19b | |||
| 1b3d713e50 | |||
| 6e816fca6e | |||
| 5a699af610 | |||
| 390119c592 | |||
| 11d7eec4db | |||
| f59be1faf2 | |||
| 7bc4c63eb4 | |||
| 4bf9f524d9 | |||
| 6508ccfc0d | |||
| d0a8d3cdc4 | |||
| 494cc1493e | |||
| 761c649817 | |||
| a2f576f3e5 | |||
| 3b9b03a086 | |||
| ab51a209d7 | |||
| 38ac339011 | |||
| b4777fe73a | |||
| b6e759f3a2 | |||
| 9ddefbc1a2 | |||
| a16851f5de | |||
| 8fe291d161 | |||
| 9ac50fc42f | |||
| c6e5221826 | |||
| 5b2006cd06 | |||
| d3f673dc6f | |||
| b99f444234 | |||
| c504096181 | |||
| c9ef47271a | |||
| fc3891c913 | |||
| cd07354b6f | |||
| fd5aeb2052 | |||
| b1b583721a | |||
| 4c3372a886 | |||
| cf66679323 | |||
| 55b41144db | |||
| ae34208247 | |||
| b462006280 | |||
| 485bcbf054 | |||
| 2e30a57889 | |||
| b439d9c203 | |||
| 08a717f5f7 | |||
| 3a84a1a5fa | |||
| 627d5fc659 | |||
| 25849dc4bb | |||
| 63032cd840 | |||
| 2414246de9 | |||
| c52353b4b8 | |||
| 799628c083 | |||
| 38d5791d57 | |||
| 9d664e2b61 | |||
| 2eb21e3521 | |||
| bfe1265c44 | |||
| dd3109cd89 | |||
| 130d5a5202 | |||
| cda4c62e9e | |||
| df245f32ec | |||
| 04409f4381 | |||
| 155e4a5b80 | |||
| 59a9209621 | |||
| cd5e14a834 | |||
| e707cf8464 | |||
| 8bdd410e97 | |||
| f45654620f | |||
| 72d138f8c4 | |||
| 6a0df7ae49 | |||
| 23def0a1c7 | |||
| 3236ef075d | |||
| d00b301904 | |||
| 6c82686283 | |||
| 399e2235d4 | |||
| bd898e4006 | |||
| 2c49dcceaf | |||
| 3c5b002414 | |||
| ca37206a49 | |||
| 8a939e981c | |||
| bed1b4cf0f | |||
| 04c3a4ccf7 | |||
| f50368a949 | |||
| 4e018dbf26 | |||
| fa02217ff4 | |||
| 22080d36b0 | |||
| 3303f4e1ce | |||
| 11d03ad59e | |||
| 504f1533c2 | |||
| bf1d1cbac5 | |||
| 94119d1674 | |||
| f4a263df01 | |||
| 533231825c | |||
| 40e2787d94 | |||
| 281af9c86f | |||
| fc0db8c291 | |||
| 48d2dbad34 | |||
| be2af8aeaf | |||
| a7621a7301 | |||
| ec87790e4f | |||
| 44632e9bf6 | |||
| 824ada49b6 | |||
| e7938216ba | |||
| 40d6d0b7b5 | |||
| 3f4d4c8eea | |||
| e2fe94d4e4 | |||
| debb5d8ad1 | |||
| f61794ea70 | |||
| d15a977431 | |||
| ef5268f78d | |||
| 7362808d5d | |||
| 27cfec68ed | |||
| ea85f40682 | |||
| 0cc38c20be | |||
| d29931a91a | |||
| 17c007348b | |||
| 33953a0d18 | |||
| 98e8e599a6 | |||
| 5e19838713 | |||
| 501803c873 | |||
| e9c2a43de1 | |||
| af94596202 | |||
| 42e87b498c | |||
| 839ff311de | |||
| ebab281471 | |||
| 582788645d | |||
| 643fed7d1c | |||
| 076324e60e | |||
| 1fe92738d8 | |||
| e319be19de | |||
| ab8448ee47 | |||
| 5493f418ed | |||
| 4e75fa958d | |||
| 0847432dd9 | |||
| e297144fe2 | |||
| 42cf88be9d | |||
| 6b008ed93b | |||
| c96d21c7c0 | |||
| 2feb53149a | |||
| e7df94495c | |||
| 42f6d029b0 | |||
| ccbb252466 | |||
| d16bdb30b9 | |||
| 8fa6aee571 | |||
| 4194e56912 | |||
| a0343d6bf7 | |||
| 44b417deca | |||
| 5ccd196ae4 | |||
| b76d6e9faa | |||
| 2d2e0ddc6d | |||
| 430da1578d | |||
| 1188db9475 | |||
| 685676bd0f | |||
| fa46dce0e1 | |||
| 2e60f34cd8 | |||
| dc50e24a29 | |||
| 1f23e93951 | |||
| 8df6409cb1 | |||
| 5c5c66d960 | |||
| 0b0e286b9c | |||
| b2130477ae | |||
| 085d0924db | |||
| 78249bf4f7 | |||
| 4c9d9f6223 | |||
| d7649d9f8f | |||
| 49e2acd15e | |||
| e4a6bf17e4 | |||
| 276e22f6b0 | |||
| b1d63e03d8 | |||
| 55f0f75c95 | |||
| fe4eb564e1 | |||
| 90ea096ca3 | |||
| 3077f885d8 | |||
| 41551ef200 | |||
| 4c96d0453e | |||
| d7ef7bc078 | |||
| c77a758741 | |||
| 12208b2c7c | |||
| 23d2cc3fdc | |||
| 1dfa0315db | |||
| f78f97a726 | |||
| 9972c61bbe | |||
| 8795d99f79 | |||
| f8aafb7ce4 | |||
| 27581d92b5 | |||
| 4a89b92185 | |||
| 1a4eb25194 | |||
| 3eb9acea2e | |||
| be860064c5 | |||
| 1985552636 | |||
| 985264d485 | |||
| 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 |
+69
-28
@@ -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,10 +44,13 @@ jobs:
|
||||
run: ctest
|
||||
|
||||
- name: run fastfetch
|
||||
run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
|
||||
run: time ./fastfetch -c presets/ci
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: ./flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
linux:
|
||||
name: Linux
|
||||
@@ -54,10 +62,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 +85,17 @@ 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 fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
@@ -103,7 +117,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 +140,17 @@ 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 fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
@@ -148,19 +168,22 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
uses: cross-platform-actions/action@v0.21.0
|
||||
with:
|
||||
prepare: |
|
||||
pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
operating_system: freebsd
|
||||
version: '13.2'
|
||||
run: |
|
||||
sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
|
||||
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 ./fastfetch -c presets/ci --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -180,14 +203,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 +236,31 @@ 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 fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci --format json
|
||||
|
||||
- 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 +273,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 +303,31 @@ 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 fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci --format json
|
||||
|
||||
- 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'
|
||||
|
||||
+171
@@ -1,3 +1,174 @@
|
||||
# 2.2.1
|
||||
|
||||
Hotfix release for #606
|
||||
|
||||
Bugfixes:
|
||||
* Fix broken presets due to the breaking changes introduced in 2.2.0
|
||||
|
||||
Features:
|
||||
* Pretty print `fastfetch --help`
|
||||
|
||||
# 2.2.0
|
||||
|
||||
This release introduces a new option `--migrate-config`, which migrates old flag based config file to new JSONC format
|
||||
|
||||
Changes:
|
||||
* `--pipe` and `--stat` are moved from `general` options to `display` options. This affects cjson configuration.
|
||||
* Display keys `percent*` and `size*` in JSON config are restructured. e.g. `{ "sizeNdigits": 1 }` is now `{ "size": { "ndigits": 1 } }`
|
||||
* With the introduction of `--migrate-config`, the old flag based config file is deprecated, and will be removed in 3.0.0 (next major version)
|
||||
* Support of `--gen-config conf` is deprecated accordingly, and will be removed in 2.3.0 (next minor version)
|
||||
* The global flag `--allow-slow-operations` is splitted into some explicit flags in differnet modules
|
||||
* `--packages-winget`: control whether `winget` packages count should be detected. Note it's a very slow operation, please enable it with caution.
|
||||
* `--chassis-use-wmi`: control whether `WMI` query should be used to detect chassis type, which detects more information, but slower. This flag only affects `--chassis-format` and `--format json`.
|
||||
* `--battery-use-setup-api`: control whether `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower.
|
||||
* `--wm-detect-plugin`: control whether WM plugins should be detected. Note it's implemented with global processes enumeration and can report false results.
|
||||
* `--de-slow-version-detection`: control DE version should be detected with slow operations. It's usually not necessary and only provided as a backup.
|
||||
* `--localip-default-route-only` and `--netio-default-route-only` defaults to true to avoid large number of results
|
||||
|
||||
Features:
|
||||
* Quirks for MIPS platforms (CPU, Linux)
|
||||
* Use devicetree path for OBP hosts (Host, Linux)
|
||||
* Detect `tmux: server` as tmux (Terminal, Linux)
|
||||
* Support urxvt version detection (Terminal, Linux)
|
||||
* Support st version detection (Terminal, Linux)
|
||||
* Support st terminal font detection (TerminalFont, Linux)
|
||||
* Support xfce4-terminal 1.1.0+ terminal font detection (TerminalFont, Linux)
|
||||
* Add option `--migrate-config <?target-file-path>`
|
||||
* Support Nvidia GPU temp and cuda core count detection via nvml. Use `--gpu-use-nvml` to enable it (GPU)
|
||||
* Try supporting Wifi authentication type detection in macOS Sonoma. Please file a feature request if you get `to be supported (num)` with result of `/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | grep auth` (Wifi, macOS)
|
||||
|
||||
Bugfixes:
|
||||
* Better GPU memory and type detection (GPU, Windows)
|
||||
* Don't print display type twice (Display)
|
||||
* Detect BSSID instead of Wifi MAC address to align with other platforms (Wifi, macOS)
|
||||
* Remove support of used GPU memory detection, which is not reliable and only supported with `--gpu-force-vulkan`. (GPU)
|
||||
* Fix flag `--brightness-ddcci-sleep` (Brightness, Linux)
|
||||
* Fix hanging if a child process prints to both stdout and stderr (Linux)
|
||||
|
||||
Logos:
|
||||
* Add Black Mesa
|
||||
* Add cycledream
|
||||
* Add Evolinx
|
||||
* Add azos
|
||||
* Add Interix
|
||||
|
||||
# 2.1.2
|
||||
|
||||
Bugfixes:
|
||||
* Fix icon detection on Windows. It shows enabled system icons in desktop (`This PC`, `Recycle Bin`, etc) (Icon, Windows)
|
||||
* Fix compatibility with ddcutil 2.0 (Brightness, Linux)
|
||||
* Fix a compile warning (CPUUsage, FreeBSD)
|
||||
|
||||
# 2.1.1
|
||||
|
||||
Features:
|
||||
* Support opkg (Packages, Linux)
|
||||
* Support GNOME Console terminal version and font detection (Terminal, Linux)
|
||||
* Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU)
|
||||
* New module to detect physical disk I/O usage (DiskIO)
|
||||
* Add `--cpuusage-separate` to display CPU usage per CPU logical core
|
||||
* Add `--brightness-ddcci-sleep` to set the sleep times (in ms) when sending DDC/CI requests (Brightness, #580)
|
||||
|
||||
Bugfixes:
|
||||
* Fix possible crashes on Windows 7 (Disk, Windows)
|
||||
* Fix possible crashes caused by uninitialized strings (Users, Windows)
|
||||
* Improve support of `--help *-format` and several bugs are found and fixed
|
||||
* Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS)
|
||||
* Fix implementation processes counting (Processes, Linux)
|
||||
* Work around a issue that SSID cannot be detected on macOS Sonoma (Wifi, macOS)
|
||||
|
||||
Logo:
|
||||
* Add Chimera Linux
|
||||
* Add EndeavourSmall
|
||||
* Add Xenia
|
||||
* Add MainsailOS
|
||||
* Fix phyOS
|
||||
|
||||
# 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:
|
||||
|
||||
+116
-14
@@ -1,9 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.0.2
|
||||
VERSION 2.2.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast system information tool"
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
)
|
||||
|
||||
@@ -67,10 +67,12 @@ 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(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" 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
|
||||
|
||||
@@ -96,12 +98,15 @@ endif()
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")
|
||||
|
||||
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()
|
||||
|
||||
@@ -112,8 +117,9 @@ 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(ENABLE_ASAN)
|
||||
message(STATUS "Address sanitizer enabled (DEBUG only)")
|
||||
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}")
|
||||
@@ -121,8 +127,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)
|
||||
@@ -218,6 +224,9 @@ fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
|
||||
|
||||
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
|
||||
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
|
||||
if(APPLE)
|
||||
configure_file(src/util/apple/Info.plist.in Info.plist @ONLY)
|
||||
endif()
|
||||
|
||||
####################
|
||||
# Ascii image data #
|
||||
@@ -259,6 +268,7 @@ set(LIBFASTFETCH_SRC
|
||||
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
|
||||
@@ -267,26 +277,28 @@ 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/diskio/diskio.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
|
||||
src/logo/image/image.c
|
||||
src/logo/logo.c
|
||||
src/logo/option.c
|
||||
src/modules/battery/battery.c
|
||||
src/modules/bios/bios.c
|
||||
src/modules/bluetooth/bluetooth.c
|
||||
@@ -303,6 +315,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/datetime/datetime.c
|
||||
src/modules/de/de.c
|
||||
src/modules/disk/disk.c
|
||||
src/modules/diskio/diskio.c
|
||||
src/modules/font/font.c
|
||||
src/modules/gpu/gpu.c
|
||||
src/modules/host/host.c
|
||||
@@ -314,6 +327,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
|
||||
@@ -342,6 +356,11 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/wifi/wifi.c
|
||||
src/modules/wm/wm.c
|
||||
src/modules/wmtheme/wmtheme.c
|
||||
src/options/display.c
|
||||
src/options/modules.c
|
||||
src/options/logo.c
|
||||
src/options/general.c
|
||||
src/options/library.c
|
||||
src/util/edidHelper.c
|
||||
src/util/FFlist.c
|
||||
src/util/FFstrbuf.c
|
||||
@@ -354,6 +373,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
|
||||
@@ -366,6 +386,7 @@ if(LINUX)
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/diskio/diskio_linux.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
@@ -373,15 +394,18 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/libc/libc_linux.c
|
||||
src/detection/lm/lm_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_linux.c
|
||||
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
|
||||
@@ -399,12 +423,15 @@ if(LINUX)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_linux.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
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
|
||||
@@ -417,17 +444,20 @@ elseif(ANDROID)
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/cpuusage/cpuusage_linux.c
|
||||
src/detection/disk/disk_linux.c
|
||||
src/detection/diskio/diskio_linux.c
|
||||
src/detection/displayserver/displayserver_android.c
|
||||
src/detection/font/font_nosupport.c
|
||||
src/detection/gpu/gpu_nosupport.c
|
||||
src/detection/host/host_android.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/libc/libc_android.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
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
|
||||
@@ -444,6 +474,8 @@ elseif(ANDROID)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wifi/wifi_android.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
@@ -451,6 +483,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
|
||||
@@ -464,6 +497,7 @@ elseif(BSD)
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/diskio/diskio_bsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/wayland.c
|
||||
src/detection/displayserver/linux/wmde.c
|
||||
@@ -471,15 +505,18 @@ elseif(BSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
src/detection/lm/lm_linux.c
|
||||
src/detection/icons/icons_linux.c
|
||||
src/detection/libc/libc_bsd.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_bsd.c
|
||||
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
|
||||
@@ -497,12 +534,15 @@ elseif(BSD)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_bsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
)
|
||||
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
|
||||
@@ -515,19 +555,21 @@ 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/diskio/diskio_apple.c
|
||||
src/detection/displayserver/displayserver_apple.c
|
||||
src/detection/font/font_apple.m
|
||||
src/detection/gpu/gpu_apple.c
|
||||
src/detection/host/host_apple.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/libc/libc_apple.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_apple.c
|
||||
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
|
||||
@@ -544,6 +586,8 @@ elseif(APPLE)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_apple.c
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wm/wm_apple.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
@@ -552,6 +596,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
|
||||
@@ -564,17 +609,21 @@ elseif(WIN32)
|
||||
src/detection/cpuusage/cpuusage_windows.c
|
||||
src/detection/cursor/cursor_windows.c
|
||||
src/detection/disk/disk_windows.c
|
||||
src/detection/diskio/diskio_windows.c
|
||||
src/detection/displayserver/displayserver_windows.c
|
||||
src/detection/font/font_windows.c
|
||||
src/detection/gpu/gpu_windows.c
|
||||
src/detection/gpu/gpu_nvidia.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_windows.c
|
||||
src/detection/libc/libc_windows.cpp
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/localip/localip_windows.c
|
||||
src/detection/gamepad/gamepad_windows.c
|
||||
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
|
||||
@@ -591,6 +640,8 @@ elseif(WIN32)
|
||||
src/detection/users/users_windows.c
|
||||
src/detection/wallpaper/wallpaper_windows.c
|
||||
src/detection/wifi/wifi_windows.c
|
||||
src/detection/wm/wm_windows.cpp
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
@@ -601,6 +652,11 @@ 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)
|
||||
@@ -623,14 +679,39 @@ endif()
|
||||
add_library(libfastfetch OBJECT
|
||||
${LIBFASTFETCH_SRC}
|
||||
)
|
||||
|
||||
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)
|
||||
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
|
||||
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
|
||||
ERROR_VARIABLE LD_MUSL_RESULT)
|
||||
if("${LD_MUSL_RESULT}" MATCHES "Version ([0-9]+\\.[0-9]+\\.[0-9]+)")
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
if(APPLE AND EXISTS "/usr/bin/otool")
|
||||
execute_process(COMMAND /usr/bin/otool -L /usr/bin/otool
|
||||
OUTPUT_VARIABLE OTOOL_OTOOL_RESULT)
|
||||
if("${OTOOL_OTOOL_RESULT}" MATCHES "libSystem\\.B\\.dylib \\(.*current version ([0-9]+\\.[0-9]+\\.[0-9]+)\\)")
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
if(BSD AND EXISTS "/usr/local/bin/objdump")
|
||||
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1"
|
||||
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
|
||||
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
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)
|
||||
@@ -773,6 +854,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)
|
||||
@@ -802,8 +887,11 @@ elseif(APPLE)
|
||||
PRIVATE "-framework OpenCL"
|
||||
PRIVATE "-framework SystemConfiguration"
|
||||
PRIVATE "-weak_framework CoreDisplay"
|
||||
PRIVATE "-weak_framework DisplayServices -F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
|
||||
|
||||
PRIVATE "-F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework DisplayServices"
|
||||
PRIVATE "-weak_framework MediaRemote"
|
||||
PRIVATE "-weak_framework Apple80211"
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601)
|
||||
@@ -827,6 +915,7 @@ elseif(BSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "usbhid"
|
||||
PRIVATE "devstat"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
@@ -877,6 +966,12 @@ target_link_libraries(flashfetch
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
# 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
|
||||
@@ -887,6 +982,13 @@ if(WIN32)
|
||||
target_sources(flashfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_options(fastfetch
|
||||
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
|
||||
)
|
||||
target_link_options(flashfetch
|
||||
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
|
||||
)
|
||||
endif()
|
||||
|
||||
###################
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -14,144 +23,53 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for
|
||||
|
||||
There are [screenshots on different platforms](https://github.com/fastfetch-cli/fastfetch/wiki)
|
||||
|
||||
## Customization
|
||||
## Installation
|
||||
|
||||
With customization and speed being two competing goals, this project actually builds two executables:
|
||||
### Linux
|
||||
|
||||
* The main one is `fastfetch`, which can be very greatly configured via flags. These flags can be made persistent by modifying `$XDG_CONFIG_HOME/fastfetch/config.conf`. Use `fastfetch --gen-config conf` to generate one. To view the available options, run `fastfetch --help`.
|
||||
* The second executable is called `flashfetch`, which is configured at compile time to eliminate any possible overhead. Configuration of it can be very easily done in [`src/flashfetch.c`](src/flashfetch.c).
|
||||
* Debian / Ubuntu: Download `fastfetch-<version>-Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `sudo apt install fastfetch-<version>-Linux.deb`
|
||||
* Arch Linux: `sudo pacman -S fastfetch`
|
||||
* Fedora: `sudo dnf install fastfetch`
|
||||
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
|
||||
|
||||
Currently, the performance difference is measurable, but too small to be recognizable by humans. But with more options planned, the leap will get bigger over time and on slow machines this might actually make a difference.
|
||||
|
||||
There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `--load-config <filename>`. They may also serve as a good example for format arguments.
|
||||
|
||||
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
### Customization with new JSONC format
|
||||
|
||||
A new, structure based, and user-friendly config file format was introduced in v2.0.0. This format is based on [JSONC](https://jsonc.org/). [See more details in Wiki](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration)
|
||||
|
||||
## Dependencies
|
||||
|
||||
Fastfetch dynamically loads needed libraries if they are available. On Linux, its only hard dependencies are `libc` (any implementation of the c standard library), `libdl`, `libm` and [`libpthread`](https://man7.org/linux/man-pages/man7/pthreads.7.html) (if built with multithreading support). They are all shipped with [`glibc`](https://www.gnu.org/software/libc/), which is already installed on most Linux distributions.
|
||||
|
||||
The following libraries are used if present at runtime:
|
||||
|
||||
### Linux and FreeBSD
|
||||
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module & fallback for GPU output.
|
||||
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||
[`libxcb`](https://xcb.freedesktop.org/),
|
||||
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better display detection and faster WM detection. The `*randr` ones provide multi monitor support The `libxcb*` ones usually have better performance.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better display performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel or kitty graphics protocol.
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art.
|
||||
* [`libZ`](https://www.zlib.net/): Faster image output when using kitty graphics protocol.
|
||||
* [`libDBus`](https://www.freedesktop.org/wiki/Software/dbus): Bluetooth, Player & Media detection.
|
||||
* [`libEGL`](https://www.khronos.org/registry/EGL/),
|
||||
[`libGLX`](https://dri.freedesktop.org/wiki/GLX/),
|
||||
[`libOSMesa`](https://docs.mesa3d.org/osmesa.html): At least one of them is needed by the OpenGL module for gl context creation.
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
|
||||
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
|
||||
* [`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
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging)
|
||||
|
||||
### macOS
|
||||
|
||||
* [`MediaRemote`](https://iphonedev.wiki/index.php/MediaRemote.framework): Need for Media detection. It's a private framework provided by newer macOS system.
|
||||
* [`DisplayServices`](https://developer.apple.com/forums/thread/666383#663154022): Need for screen brightness detection. It's a private framework provided by newer macOS system.
|
||||
* [`MoltenVK`](https://github.com/KhronosGroup/MoltenVK): Vulkan driver for macOS. [`molten-vk`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/molten-vk.rb)
|
||||
* [`libmagickcore` (ImageMagick)](https://www.imagemagick.org/): Images in terminal using sixel graphics protocol. [`imagemagick`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb)
|
||||
* [`libchafa`](https://github.com/hpjansson/chafa): Image output as ascii art. [`chafa`](https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb)
|
||||
* [`libsqlite3`](https://www.sqlite.org/index.html): Used for fast wallpaper detection ( fallback to AppleScript )
|
||||
|
||||
For the image logo, iTerm with iterm image protocol should work. Apple Terminal is not supported.
|
||||
`brew install fastfetch`
|
||||
|
||||
### Windows
|
||||
|
||||
* [`wlanapi`](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/): A system dll which isn't supported by Windows Server by default. Used for Wifi info detection.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module. Usually has been provided by GPU drivers. [`vulkan-loader`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-loader) [`vulkan-headers`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-vulkan-headers)
|
||||
* [`libOpenCL`](https://www.khronos.org/opencl/): OpenCL module. [`opencl-icd`](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-opencl-icd)
|
||||
`scoop install fastfetch`
|
||||
|
||||
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.
|
||||
You may also download it directly from [GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and extract the archive.
|
||||
|
||||
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.
|
||||
### FreeBSD
|
||||
|
||||
### Android
|
||||
`pkg install fastfetch`
|
||||
|
||||
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
|
||||
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
|
||||
* [`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.
|
||||
### Android (Termux)
|
||||
|
||||
## Support status
|
||||
All categories not listed here should work without needing a specific implementation.
|
||||
`pkg install fastfetch`
|
||||
|
||||
##### 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, 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
|
||||
```
|
||||
## Build from source
|
||||
|
||||
##### Builtin logos
|
||||
See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
<!-- `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(', ') -->
|
||||
```
|
||||
AerOS, 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, 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, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin
|
||||
```
|
||||
## Usage
|
||||
|
||||
Run `fastfetch --print-logos` to print them
|
||||
* Run it with default configuration: `fastfetch`
|
||||
* Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what you interest: `fastfetch -c all.jsonc`
|
||||
* Find all data that fastfetch detects: `fastfetch -s <module> --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --mirgrate-config`
|
||||
|
||||
##### Package managers
|
||||
```
|
||||
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps
|
||||
```
|
||||
## Customization
|
||||
|
||||
##### WM themes
|
||||
```
|
||||
DWM (Windows), KWin, Marco, Muffin, Mutter, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), XFWM
|
||||
```
|
||||
Fastfetch uses the JSONC (or JSON with comments) for configuration. [See Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `-c <filename>`. They may also serve as a good example for format arguments.
|
||||
|
||||
##### DE versions
|
||||
```
|
||||
Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
|
||||
```
|
||||
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
##### Terminal fonts
|
||||
```
|
||||
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
fastfetch uses [`cmake`](https://cmake.org/) for building. [`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) is recommended for better library detection. The simplest steps to build the fastfetch and flashfetch binaries are:
|
||||
```bash
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --target fastfetch --target flashfetch
|
||||
```
|
||||
|
||||
If the build process fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
|
||||
|
||||
### Building on Windows
|
||||
|
||||
Currently GCC or clang is required (MSVC is not supported). MSYS2 with CLANG64 subsystem (or CLANGARM64 if needed) is suggested (and tested) to build fastfetch. If you need Windows 7 / 8.x support, using MINGW64 is suggested.
|
||||
|
||||
1. Install [MSYS2](https://www.msys2.org/#installation)
|
||||
1. Open `MSYS2 / CLANG64` (not `MSYS2 / MSYS`, which targets cygwin C runtime)
|
||||
1. Install dependencies
|
||||
```bash
|
||||
pacman -Syu mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-pkgconf mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-opencl-icd
|
||||
```
|
||||
|
||||
Follow the building instructions of Linux next.
|
||||
|
||||
## Packaging
|
||||
|
||||
|
||||
+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"
|
||||
|
||||
+571
-212
File diff suppressed because it is too large
Load Diff
+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:Version: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:DiskIO:Version:Break:Colors
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
"sound",
|
||||
"gamepad",
|
||||
"weather",
|
||||
"netio",
|
||||
"diskio",
|
||||
"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,40 @@
|
||||
{
|
||||
"$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percent": {
|
||||
"type": 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,9 +8,13 @@
|
||||
"color": {
|
||||
"keys": "magenta"
|
||||
},
|
||||
"sizeNdigits": 0,
|
||||
"sizeMaxPrefix": "MB",
|
||||
"percentType": 9
|
||||
"size": {
|
||||
"ndigits": 0,
|
||||
"maxPrefix": "MB"
|
||||
},
|
||||
"percent": {
|
||||
"type": 9
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
"type": "small"
|
||||
},
|
||||
"display": {
|
||||
"percentType": 6,
|
||||
"keyWidth": 11,
|
||||
"bar": {
|
||||
"charElapsed": "=",
|
||||
"charTotal": "-",
|
||||
"width": 13
|
||||
},
|
||||
"percent": {
|
||||
"type": 9
|
||||
}
|
||||
},
|
||||
"modules": [
|
||||
|
||||
@@ -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
+10359
File diff suppressed because it is too large
Load Diff
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/NVIDIA/nvidia-settings/blob/main/src/nvml.h",
|
||||
"license": "Embed in source",
|
||||
"version": "545.23.06",
|
||||
"author": "NVIDIA Corporation"
|
||||
}
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ibireme/yyjson",
|
||||
"license": "MIT ( embed in source )",
|
||||
"version": "5e3b26d2659287d31e2f8e10f95f95feb7e5ab3a",
|
||||
"version": "0.8.0",
|
||||
"author": "ibireme"
|
||||
}
|
||||
|
||||
Vendored
+217
-51
@@ -307,6 +307,9 @@ uint32_t yyjson_version(void) {
|
||||
#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val))
|
||||
#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val))
|
||||
|
||||
/* The minimum size of the dynamic allocator's chunk. */
|
||||
#define YYJSON_ALC_DYN_MIN_SIZE 0x1000
|
||||
|
||||
/* Default value for compile-time options. */
|
||||
#ifndef YYJSON_DISABLE_READER
|
||||
#define YYJSON_DISABLE_READER 0
|
||||
@@ -966,6 +969,15 @@ static const yyjson_alc YYJSON_DEFAULT_ALC = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* Null Memory Allocator
|
||||
*
|
||||
* This allocator is just a placeholder to ensure that the internal
|
||||
* malloc/realloc/free function pointers are not null.
|
||||
*============================================================================*/
|
||||
|
||||
static void *null_malloc(void *ctx, usize size) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -989,29 +1001,37 @@ static const yyjson_alc YYJSON_NULL_ALC = {
|
||||
|
||||
/*==============================================================================
|
||||
* Pool Memory Allocator
|
||||
* This is a simple memory allocator that uses linked list memory chunk.
|
||||
* The following code will be executed only when the library user creates
|
||||
* this allocator manually.
|
||||
*
|
||||
* This allocator is initialized with a fixed-size buffer.
|
||||
* The buffer is split into multiple memory chunks for memory allocation.
|
||||
*============================================================================*/
|
||||
|
||||
/** chunk header */
|
||||
/** memory chunk header */
|
||||
typedef struct pool_chunk {
|
||||
usize size; /* chunk memory size (include chunk header) */
|
||||
struct pool_chunk *next;
|
||||
usize size; /* chunk memory size, include chunk header */
|
||||
struct pool_chunk *next; /* linked list, nullable */
|
||||
/* char mem[]; flexible array member */
|
||||
} pool_chunk;
|
||||
|
||||
/** ctx header */
|
||||
/** allocator ctx header */
|
||||
typedef struct pool_ctx {
|
||||
usize size; /* total memory size (include ctx header) */
|
||||
pool_chunk *free_list;
|
||||
usize size; /* total memory size, include ctx header */
|
||||
pool_chunk *free_list; /* linked list, nullable */
|
||||
/* pool_chunk chunks[]; flexible array member */
|
||||
} pool_ctx;
|
||||
|
||||
/** align up the input size to chunk size */
|
||||
static_inline void pool_size_align(usize *size) {
|
||||
*size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk);
|
||||
}
|
||||
|
||||
static void *pool_malloc(void *ctx_ptr, usize size) {
|
||||
/* assert(size != 0) */
|
||||
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
|
||||
pool_chunk *next, *prev = NULL, *cur = ctx->free_list;
|
||||
|
||||
if (unlikely(size == 0 || size >= ctx->size)) return NULL;
|
||||
size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk);
|
||||
if (unlikely(size >= ctx->size)) return NULL;
|
||||
pool_size_align(&size);
|
||||
|
||||
while (cur) {
|
||||
if (cur->size < size) {
|
||||
@@ -1038,6 +1058,7 @@ static void *pool_malloc(void *ctx_ptr, usize size) {
|
||||
}
|
||||
|
||||
static void pool_free(void *ctx_ptr, void *ptr) {
|
||||
/* assert(ptr != NULL) */
|
||||
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
|
||||
pool_chunk *cur = ((pool_chunk *)ptr) - 1;
|
||||
pool_chunk *prev = NULL, *next = ctx->free_list;
|
||||
@@ -1064,25 +1085,15 @@ static void pool_free(void *ctx_ptr, void *ptr) {
|
||||
|
||||
static void *pool_realloc(void *ctx_ptr, void *ptr,
|
||||
usize old_size, usize size) {
|
||||
/* assert(ptr != NULL && size != 0 && old_size < size) */
|
||||
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
|
||||
pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp;
|
||||
usize free_size;
|
||||
void *new_ptr;
|
||||
|
||||
if (unlikely(size == 0 || size >= ctx->size)) return NULL;
|
||||
size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk);
|
||||
|
||||
/* reduce size */
|
||||
if (unlikely(size <= cur->size)) {
|
||||
free_size = cur->size - size;
|
||||
if (free_size >= sizeof(pool_chunk) * 2) {
|
||||
tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size);
|
||||
tmp->size = free_size;
|
||||
pool_free(ctx_ptr, (void *)(tmp + 1));
|
||||
cur->size -= free_size;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
/* check size */
|
||||
if (unlikely(size >= ctx->size)) return NULL;
|
||||
pool_size_align(&old_size);
|
||||
pool_size_align(&size);
|
||||
if (unlikely(old_size == size)) return ptr;
|
||||
|
||||
/* find next and prev chunk */
|
||||
prev = NULL;
|
||||
@@ -1092,10 +1103,9 @@ static void *pool_realloc(void *ctx_ptr, void *ptr,
|
||||
next = next->next;
|
||||
}
|
||||
|
||||
/* merge to higher chunk if they are contiguous */
|
||||
if ((u8 *)cur + cur->size == (u8 *)next &&
|
||||
cur->size + next->size >= size) {
|
||||
free_size = cur->size + next->size - size;
|
||||
if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) {
|
||||
/* merge to higher chunk if they are contiguous */
|
||||
usize free_size = cur->size + next->size - size;
|
||||
if (free_size > sizeof(pool_chunk) * 2) {
|
||||
tmp = (pool_chunk *)(void *)((u8 *)cur + size);
|
||||
if (prev) prev->next = tmp;
|
||||
@@ -1109,15 +1119,15 @@ static void *pool_realloc(void *ctx_ptr, void *ptr,
|
||||
cur->size += next->size;
|
||||
}
|
||||
return ptr;
|
||||
} else {
|
||||
/* fallback to malloc and memcpy */
|
||||
void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk));
|
||||
if (new_ptr) {
|
||||
memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk));
|
||||
pool_free(ctx_ptr, ptr);
|
||||
}
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
/* fallback to malloc and memcpy */
|
||||
new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk));
|
||||
if (new_ptr) {
|
||||
memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk));
|
||||
pool_free(ctx_ptr, ptr);
|
||||
}
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) {
|
||||
@@ -1147,6 +1157,161 @@ bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) {
|
||||
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* Dynamic Memory Allocator
|
||||
*
|
||||
* This allocator allocates memory on demand and does not immediately release
|
||||
* unused memory. Instead, it places the unused memory into a freelist for
|
||||
* potential reuse in the future. It is only when the entire allocator is
|
||||
* destroyed that all previously allocated memory is released at once.
|
||||
*============================================================================*/
|
||||
|
||||
/** memory chunk header */
|
||||
typedef struct dyn_chunk {
|
||||
usize size; /* chunk size, include header */
|
||||
struct dyn_chunk *next;
|
||||
/* char mem[]; flexible array member */
|
||||
} dyn_chunk;
|
||||
|
||||
/** allocator ctx header */
|
||||
typedef struct {
|
||||
dyn_chunk free_list; /* dummy header, sorted from small to large */
|
||||
dyn_chunk used_list; /* dummy header */
|
||||
} dyn_ctx;
|
||||
|
||||
/** align up the input size to chunk size */
|
||||
static_inline bool dyn_size_align(usize *size) {
|
||||
usize alc_size = *size + sizeof(dyn_chunk);
|
||||
alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE);
|
||||
if (unlikely(alc_size < *size)) return false; /* overflow */
|
||||
*size = alc_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** remove a chunk from list (the chunk must already be in the list) */
|
||||
static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) {
|
||||
dyn_chunk *prev = list, *cur;
|
||||
for (cur = prev->next; cur; cur = cur->next) {
|
||||
if (cur == chunk) {
|
||||
prev->next = cur->next;
|
||||
cur->next = NULL;
|
||||
return;
|
||||
}
|
||||
prev = cur;
|
||||
}
|
||||
}
|
||||
|
||||
/** add a chunk to list header (the chunk must not be in the list) */
|
||||
static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) {
|
||||
chunk->next = list->next;
|
||||
list->next = chunk;
|
||||
}
|
||||
|
||||
static void *dyn_malloc(void *ctx_ptr, usize size) {
|
||||
/* assert(size != 0) */
|
||||
const yyjson_alc def = YYJSON_DEFAULT_ALC;
|
||||
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
|
||||
dyn_chunk *chunk, *prev, *next;
|
||||
if (unlikely(!dyn_size_align(&size))) return NULL;
|
||||
|
||||
/* freelist is empty, create new chunk */
|
||||
if (!ctx->free_list.next) {
|
||||
chunk = (dyn_chunk *)def.malloc(def.ctx, size);
|
||||
if (unlikely(!chunk)) return NULL;
|
||||
chunk->size = size;
|
||||
chunk->next = NULL;
|
||||
dyn_chunk_list_add(&ctx->used_list, chunk);
|
||||
return (void *)(chunk + 1);
|
||||
}
|
||||
|
||||
/* find a large enough chunk, or resize the largest chunk */
|
||||
prev = &ctx->free_list;
|
||||
while (true) {
|
||||
chunk = prev->next;
|
||||
if (chunk->size >= size) { /* enough size, reuse this chunk */
|
||||
prev->next = chunk->next;
|
||||
dyn_chunk_list_add(&ctx->used_list, chunk);
|
||||
return (void *)(chunk + 1);
|
||||
}
|
||||
if (!chunk->next) { /* resize the largest chunk */
|
||||
chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
|
||||
if (unlikely(!chunk)) return NULL;
|
||||
prev->next = NULL;
|
||||
chunk->size = size;
|
||||
dyn_chunk_list_add(&ctx->used_list, chunk);
|
||||
return (void *)(chunk + 1);
|
||||
}
|
||||
prev = chunk;
|
||||
}
|
||||
}
|
||||
|
||||
static void *dyn_realloc(void *ctx_ptr, void *ptr,
|
||||
usize old_size, usize size) {
|
||||
/* assert(ptr != NULL && size != 0 && old_size < size) */
|
||||
const yyjson_alc def = YYJSON_DEFAULT_ALC;
|
||||
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
|
||||
dyn_chunk *prev, *next, *new_chunk;
|
||||
dyn_chunk *chunk = (dyn_chunk *)ptr - 1;
|
||||
if (unlikely(!dyn_size_align(&size))) return NULL;
|
||||
if (chunk->size >= size) return ptr;
|
||||
|
||||
dyn_chunk_list_remove(&ctx->used_list, chunk);
|
||||
new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
|
||||
if (likely(new_chunk)) {
|
||||
new_chunk->size = size;
|
||||
chunk = new_chunk;
|
||||
}
|
||||
dyn_chunk_list_add(&ctx->used_list, chunk);
|
||||
return new_chunk ? (void *)(new_chunk + 1) : NULL;
|
||||
}
|
||||
|
||||
static void dyn_free(void *ctx_ptr, void *ptr) {
|
||||
/* assert(ptr != NULL) */
|
||||
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
|
||||
dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev;
|
||||
|
||||
dyn_chunk_list_remove(&ctx->used_list, chunk);
|
||||
for (prev = &ctx->free_list; prev; prev = prev->next) {
|
||||
if (!prev->next || prev->next->size >= chunk->size) {
|
||||
chunk->next = prev->next;
|
||||
prev->next = chunk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yyjson_alc *yyjson_alc_dyn_new(void) {
|
||||
const yyjson_alc def = YYJSON_DEFAULT_ALC;
|
||||
usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx);
|
||||
yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len);
|
||||
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
|
||||
if (unlikely(!alc)) return NULL;
|
||||
alc->malloc = dyn_malloc;
|
||||
alc->realloc = dyn_realloc;
|
||||
alc->free = dyn_free;
|
||||
alc->ctx = alc + 1;
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return alc;
|
||||
}
|
||||
|
||||
void yyjson_alc_dyn_free(yyjson_alc *alc) {
|
||||
const yyjson_alc def = YYJSON_DEFAULT_ALC;
|
||||
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
|
||||
dyn_chunk *chunk, *next;
|
||||
if (unlikely(!alc)) return;
|
||||
for (chunk = ctx->free_list.next; chunk; chunk = next) {
|
||||
next = chunk->next;
|
||||
def.free(def.ctx, chunk);
|
||||
}
|
||||
for (chunk = ctx->used_list.next; chunk; chunk = next) {
|
||||
next = chunk->next;
|
||||
def.free(def.ctx, chunk);
|
||||
}
|
||||
def.free(def.ctx, alc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* JSON document and value
|
||||
*============================================================================*/
|
||||
@@ -1305,7 +1470,6 @@ yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc,
|
||||
We copy them to another contiguous memory as mutable values,
|
||||
then reconnect the mutable values with the original relationship.
|
||||
*/
|
||||
|
||||
usize i_vals_len;
|
||||
yyjson_mut_val *m_vals, *m_val;
|
||||
yyjson_val *i_val, *i_end;
|
||||
@@ -1375,7 +1539,6 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc,
|
||||
second to last item, which needs to be linked to the last item to close the
|
||||
circle.
|
||||
*/
|
||||
|
||||
yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1);
|
||||
if (unlikely(!m_val)) return NULL;
|
||||
m_val->tag = m_vals->tag;
|
||||
@@ -1540,12 +1703,13 @@ static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) {
|
||||
yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni;
|
||||
yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs);
|
||||
yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs);
|
||||
if (lt == rt)
|
||||
return luni->u64 == runi->u64;
|
||||
if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT)
|
||||
if (lt == rt) return luni->u64 == runi->u64;
|
||||
if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) {
|
||||
return luni->i64 >= 0 && luni->u64 == runi->u64;
|
||||
if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT)
|
||||
}
|
||||
if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) {
|
||||
return runi->i64 >= 0 && luni->u64 == runi->u64;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1571,8 +1735,8 @@ bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
|
||||
while (len-- > 0) {
|
||||
rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str,
|
||||
unsafe_yyjson_get_len(lhs));
|
||||
if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs))
|
||||
return false;
|
||||
if (!rhs) return false;
|
||||
if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false;
|
||||
lhs = unsafe_yyjson_get_next(lhs + 1);
|
||||
}
|
||||
}
|
||||
@@ -1626,8 +1790,8 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) {
|
||||
while (len-- > 0) {
|
||||
rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str,
|
||||
unsafe_yyjson_get_len(lhs));
|
||||
if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs))
|
||||
return false;
|
||||
if (!rhs) return false;
|
||||
if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false;
|
||||
lhs = lhs->next->next;
|
||||
}
|
||||
}
|
||||
@@ -2506,6 +2670,7 @@ yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
|
||||
builder = yyjson_mut_obj(doc);
|
||||
if (unlikely(!builder)) return NULL;
|
||||
|
||||
memset(&local_orig, 0, sizeof(local_orig));
|
||||
if (!yyjson_is_obj(orig)) {
|
||||
orig = &local_orig;
|
||||
orig->tag = builder->tag;
|
||||
@@ -2557,6 +2722,7 @@ yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
|
||||
builder = yyjson_mut_obj(doc);
|
||||
if (unlikely(!builder)) return NULL;
|
||||
|
||||
memset(&local_orig, 0, sizeof(local_orig));
|
||||
if (!yyjson_mut_is_obj(orig)) {
|
||||
orig = &local_orig;
|
||||
orig->tag = builder->tag;
|
||||
@@ -3318,8 +3484,6 @@ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) {
|
||||
|
||||
|
||||
|
||||
#if !YYJSON_DISABLE_READER
|
||||
|
||||
/*==============================================================================
|
||||
* JSON Character Matcher
|
||||
*============================================================================*/
|
||||
@@ -3513,6 +3677,8 @@ static_inline bool digi_is_digit_or_fp(u8 d) {
|
||||
|
||||
|
||||
|
||||
#if !YYJSON_DISABLE_READER
|
||||
|
||||
/*==============================================================================
|
||||
* Hex Character Reader
|
||||
* This function is used by JSON reader to read escaped characters.
|
||||
|
||||
Vendored
+85
-21
@@ -527,16 +527,16 @@ extern "C" {
|
||||
#define YYJSON_VERSION_MAJOR 0
|
||||
|
||||
/** The minor version of yyjson. */
|
||||
#define YYJSON_VERSION_MINOR 7
|
||||
#define YYJSON_VERSION_MINOR 8
|
||||
|
||||
/** The patch version of yyjson. */
|
||||
#define YYJSON_VERSION_PATCH 0
|
||||
|
||||
/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
|
||||
#define YYJSON_VERSION_HEX 0x000700
|
||||
#define YYJSON_VERSION_HEX 0x000800
|
||||
|
||||
/** The version string of yyjson. */
|
||||
#define YYJSON_VERSION_STRING "0.7.0"
|
||||
#define YYJSON_VERSION_STRING "0.8.0"
|
||||
|
||||
/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
|
||||
yyjson_api uint32_t yyjson_version(void);
|
||||
@@ -635,11 +635,11 @@ typedef struct yyjson_alc {
|
||||
function, but the amount of memory required to write a JSON cannot be directly
|
||||
calculated.
|
||||
|
||||
This is not a general-purpose allocator. If used to read multiple JSON
|
||||
documents and only some of them are released, it may cause memory
|
||||
fragmentation, leading to performance degradation and memory waste. Therefore,
|
||||
it is recommended to use this allocator only for reading or writing a single
|
||||
JSON document.
|
||||
This is not a general-purpose allocator. It is designed to handle a single JSON
|
||||
data at a time. If it is used for overly complex memory tasks, such as parsing
|
||||
multiple JSON documents using the same allocator but releasing only a few of
|
||||
them, it may cause memory fragmentation, resulting in performance degradation
|
||||
and memory waste.
|
||||
|
||||
@param alc The allocator to be initialized.
|
||||
If this parameter is NULL, the function will fail and return false.
|
||||
@@ -662,9 +662,31 @@ typedef struct yyjson_alc {
|
||||
yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL);
|
||||
// the memory of `doc` is on the stack
|
||||
@endcode
|
||||
|
||||
@warning This Allocator is not thread-safe.
|
||||
*/
|
||||
yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size);
|
||||
|
||||
/**
|
||||
A dynamic allocator.
|
||||
|
||||
This allocator has a similar usage to the pool allocator above. However, when
|
||||
there is not enough memory, this allocator will dynamically request more memory
|
||||
using libc's `malloc` function, and frees it all at once when it is destroyed.
|
||||
|
||||
@return A new dynamic allocator, or NULL if memory allocation failed.
|
||||
@note The returned value should be freed with `yyjson_alc_dyn_free()`.
|
||||
|
||||
@warning This Allocator is not thread-safe.
|
||||
*/
|
||||
yyjson_api yyjson_alc *yyjson_alc_dyn_new(void);
|
||||
|
||||
/**
|
||||
Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`.
|
||||
@param alc The dynamic allocator to be destroyed.
|
||||
*/
|
||||
yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc);
|
||||
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
@@ -3556,7 +3578,7 @@ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3566,7 +3588,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3576,7 +3598,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3586,7 +3608,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3596,7 +3618,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3606,7 +3628,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3616,7 +3638,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3626,7 +3648,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3636,7 +3658,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
|
||||
The `key` and `val` should be null-terminated UTF-8 strings.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key/value string are not copied, you should keep these strings
|
||||
@warning The key/value strings are not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3648,7 +3670,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
|
||||
The `len` should be the length of the `val`, in bytes.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key/value string are not copied, you should keep these strings
|
||||
@warning The key/value strings are not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3660,7 +3682,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
|
||||
The value string is copied.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -3673,18 +3695,44 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
|
||||
The `len` should be the length of the `val`, in bytes.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key/value string are not copied, you should keep these strings
|
||||
@warning The key/value strings are not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *key,
|
||||
const char *val, size_t len);
|
||||
|
||||
/**
|
||||
Creates and adds a new array to the target object.
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string is not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document.
|
||||
@return The new array, or NULL on error.
|
||||
*/
|
||||
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *key);
|
||||
|
||||
/**
|
||||
Creates and adds a new object to the target object.
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string is not copied, you should keep these strings
|
||||
unmodified for the lifetime of this JSON document.
|
||||
@return The new object, or NULL on error.
|
||||
*/
|
||||
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *key);
|
||||
|
||||
/** Adds a JSON value at the end of the object.
|
||||
The `key` should be a null-terminated UTF-8 string.
|
||||
This function allows duplicated key in one object.
|
||||
|
||||
@warning The key string are not copied, you should keep the string
|
||||
@warning The key string is not copied, you should keep the string
|
||||
unmodified for the lifetime of this JSON document. */
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
@@ -6920,6 +6968,22 @@ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
|
||||
});
|
||||
}
|
||||
|
||||
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *_key) {
|
||||
yyjson_mut_val *key = yyjson_mut_str(doc, _key);
|
||||
yyjson_mut_val *val = yyjson_mut_arr(doc);
|
||||
return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
|
||||
}
|
||||
|
||||
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *_key) {
|
||||
yyjson_mut_val *key = yyjson_mut_str(doc, _key);
|
||||
yyjson_mut_val *val = yyjson_mut_obj(doc);
|
||||
return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
|
||||
}
|
||||
|
||||
yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj,
|
||||
const char *_key,
|
||||
|
||||
+27
-21
@@ -6,15 +6,17 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100 && red <= 100);
|
||||
|
||||
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);
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
if(instance.config.barBorder)
|
||||
uint32_t blocksPercent = (uint32_t) (percent / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksGreen = (uint32_t) (green / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksYellow = (uint32_t) (yellow / 100.0 * options->barWidth + 0.5);
|
||||
uint32_t blocksRed = (uint32_t) (red / 100.0 * options->barWidth + 0.5);
|
||||
assert(blocksPercent <= options->barWidth);
|
||||
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m[ ");
|
||||
else
|
||||
ffStrbufAppendS(buffer, "[ ");
|
||||
@@ -22,7 +24,7 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
{
|
||||
if (i == blocksGreen)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
@@ -31,26 +33,26 @@ void ffAppendPercentBar(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
else if (i == blocksRed)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
ffStrbufAppend(buffer, &instance.config.barCharElapsed);
|
||||
ffStrbufAppend(buffer, &options->barCharElapsed);
|
||||
}
|
||||
|
||||
if (blocksPercent < instance.config.barWidth)
|
||||
if (blocksPercent < options->barWidth)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m");
|
||||
for (uint32_t i = blocksPercent; i < instance.config.barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &instance.config.barCharTotal);
|
||||
for (uint32_t i = blocksPercent; i < options->barWidth; ++i)
|
||||
ffStrbufAppend(buffer, &options->barCharTotal);
|
||||
}
|
||||
|
||||
if(instance.config.barBorder)
|
||||
if(options->barBorder)
|
||||
{
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_WHITE "m ]");
|
||||
else
|
||||
ffStrbufAppendS(buffer, " ]");
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!options->pipe)
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
@@ -67,14 +69,18 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
{
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
bool colored = !!(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
|
||||
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
|
||||
if (colored && !instance.config.pipe)
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
if(green < yellow)
|
||||
if(percent != percent)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_BLACK "m");
|
||||
else if(green < yellow)
|
||||
{
|
||||
if (percent <= green)
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_GREEN "m");
|
||||
@@ -93,9 +99,9 @@ void ffAppendPercentNum(FFstrbuf* buffer, double percent, uint8_t green, uint8_t
|
||||
ffStrbufAppendS(buffer, "\e[" FF_COLOR_FG_LIGHT_RED "m");
|
||||
}
|
||||
}
|
||||
ffStrbufAppendF(buffer, "%u%%", (unsigned) (percent + 0.5));
|
||||
ffStrbufAppendF(buffer, "%.*f%%", options->percentNdigits, percent);
|
||||
|
||||
if (colored && !instance.config.pipe)
|
||||
if (colored && !options->pipe)
|
||||
{
|
||||
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
|
||||
+168
-16
@@ -1,23 +1,13 @@
|
||||
#include "commandoption.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/time.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
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))
|
||||
{
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#include <inttypes.h>
|
||||
|
||||
bool ffParseModuleOptions(const char* key, const char* value)
|
||||
{
|
||||
@@ -30,3 +20,165 @@ bool ffParseModuleOptions(const char* key, const char* value)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffPrepareCommandOption(FFdata* data)
|
||||
{
|
||||
FFOptionsModules* const options = &instance.config.modules;
|
||||
//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_DISKIO_MODULE_NAME))
|
||||
ffPrepareDiskIO(&options->diskIo);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
|
||||
ffPrepareNetIO(&options->netIo);
|
||||
|
||||
if(instance.config.general.multithreading)
|
||||
{
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
|
||||
ffPreparePublicIp(&options->publicIP);
|
||||
|
||||
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
|
||||
ffPrepareWeather(&options->weather);
|
||||
}
|
||||
}
|
||||
|
||||
static void genJsonConfig(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
|
||||
if (!modules)
|
||||
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
|
||||
|
||||
yyjson_mut_val* module = yyjson_mut_obj(doc);
|
||||
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
|
||||
ffStrbufLowerCase(&type);
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
|
||||
|
||||
if (baseInfo->generateJsonConfig)
|
||||
baseInfo->generateJsonConfig(baseInfo, doc, module);
|
||||
|
||||
if (yyjson_mut_obj_size(module) > 1)
|
||||
yyjson_mut_arr_add_val(modules, module);
|
||||
else
|
||||
yyjson_mut_arr_add_strbuf(doc, modules, &type);
|
||||
}
|
||||
|
||||
static void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
baseInfo->generateJsonResult(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
}
|
||||
|
||||
static void parseStructureCommand(
|
||||
const char* line,
|
||||
FFlist* customValues,
|
||||
void (*fn)(FFModuleBaseInfo *baseInfo, yyjson_mut_doc* jsonDoc),
|
||||
yyjson_mut_doc* jsonDoc
|
||||
)
|
||||
{
|
||||
// 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);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn((FFModuleBaseInfo*) &options, jsonDoc);
|
||||
else
|
||||
ffPrintCustom(&options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(isalpha(line[0]))
|
||||
{
|
||||
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
|
||||
{
|
||||
FFModuleBaseInfo* baseInfo = *modules;
|
||||
if (ffStrEqualsIgnCase(line, baseInfo->name))
|
||||
{
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
fn(baseInfo, jsonDoc);
|
||||
else
|
||||
baseInfo->printModule(baseInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
|
||||
}
|
||||
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//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.display.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonResult, jsonDoc);
|
||||
|
||||
if(instance.config.display.stat)
|
||||
{
|
||||
ms = ffTimeGetTick() - ms;
|
||||
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_uint(jsonDoc, moduleJson, "stat", ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
|
||||
if(instance.config.display.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 (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
|
||||
#endif
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
//If we don't have a custom structure, use the default one
|
||||
if(data->structure.length == 0)
|
||||
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
|
||||
|
||||
//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';
|
||||
|
||||
parseStructureCommand(data->structure.chars + startIndex, &data->customValues, genJsonConfig, jsonDoc);
|
||||
|
||||
startIndex = colonIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,24 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
bool ffParseModuleCommand(const char* type);
|
||||
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 ffParseModuleOptions(const char* key, const char* value);
|
||||
void ffPrepareCommandOption(FFdata* data);
|
||||
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-5
@@ -7,7 +7,7 @@
|
||||
|
||||
static bool loadLibSymbols(FFDBusLibrary* lib)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dbus, &instance.config.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_init, false)
|
||||
@@ -33,9 +33,6 @@ static const FFDBusLibrary* loadLib(void)
|
||||
static FFDBusLibrary lib;
|
||||
static bool loaded = false;
|
||||
static bool loadSuccess = false;
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ffThreadMutexLock(&mutex);
|
||||
|
||||
if(!loaded)
|
||||
{
|
||||
@@ -43,7 +40,6 @@ static const FFDBusLibrary* loadLib(void)
|
||||
loadSuccess = loadLibSymbols(&lib);
|
||||
}
|
||||
|
||||
ffThreadMutexUnlock(&mutex);
|
||||
return loadSuccess ? &lib : NULL;
|
||||
}
|
||||
|
||||
|
||||
+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,
|
||||
|
||||
+22
-248
@@ -15,8 +15,6 @@
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "modules/modules.h"
|
||||
|
||||
FFinstance instance; // Global singleton
|
||||
|
||||
static void initState(FFstate* state)
|
||||
@@ -27,134 +25,16 @@ static void initState(FFstate* state)
|
||||
|
||||
ffPlatformInit(&state->platform);
|
||||
state->configDoc = NULL;
|
||||
state->resultDoc = NULL;
|
||||
}
|
||||
|
||||
static void defaultConfig(void)
|
||||
{
|
||||
ffInitLogoOptions(&instance.config.logo);
|
||||
|
||||
ffStrbufInit(&instance.config.colorKeys);
|
||||
ffStrbufInit(&instance.config.colorTitle);
|
||||
instance.config.brightColor = true;
|
||||
ffStrbufInitStatic(&instance.config.keyValueSeparator, ": ");
|
||||
instance.config.processingTimeout = 1000;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
ffStrbufInit(&instance.config.playerName);
|
||||
ffStrbufInit(&instance.config.osFile);
|
||||
instance.config.dsForceDrm = false;
|
||||
#elif defined(_WIN32)
|
||||
instance.config.wmiTimeout = 5000;
|
||||
#endif
|
||||
|
||||
instance.config.showErrors = false;
|
||||
instance.config.allowSlowOperations = false;
|
||||
instance.config.pipe = !isatty(STDOUT_FILENO);
|
||||
|
||||
#ifdef NDEBUG
|
||||
instance.config.disableLinewrap = !instance.config.pipe;
|
||||
instance.config.hideCursor = !instance.config.pipe;
|
||||
#else
|
||||
instance.config.disableLinewrap = false;
|
||||
instance.config.hideCursor = false;
|
||||
#endif
|
||||
|
||||
instance.config.escapeBedrock = true;
|
||||
instance.config.binaryPrefixType = FF_BINARY_PREFIX_TYPE_IEC;
|
||||
instance.config.sizeNdigits = 2;
|
||||
instance.config.sizeMaxPrefix = UINT8_MAX;
|
||||
instance.config.temperatureUnit = FF_TEMPERATURE_UNIT_CELSIUS;
|
||||
instance.config.multithreading = true;
|
||||
instance.config.stat = false;
|
||||
instance.config.noBuffer = false;
|
||||
instance.config.keyWidth = 0;
|
||||
|
||||
ffStrbufInitStatic(&instance.config.barCharElapsed, "■");
|
||||
ffStrbufInitStatic(&instance.config.barCharTotal, "-");
|
||||
instance.config.barWidth = 10;
|
||||
instance.config.barBorder = true;
|
||||
instance.config.percentType = 1;
|
||||
|
||||
ffInitBatteryOptions(&instance.config.battery);
|
||||
ffInitBiosOptions(&instance.config.bios);
|
||||
ffInitBluetoothOptions(&instance.config.bluetooth);
|
||||
ffInitBoardOptions(&instance.config.board);
|
||||
ffInitBreakOptions(&instance.config.break_);
|
||||
ffInitBrightnessOptions(&instance.config.brightness);
|
||||
ffInitCPUOptions(&instance.config.cpu);
|
||||
ffInitCPUUsageOptions(&instance.config.cpuUsage);
|
||||
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);
|
||||
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);
|
||||
ffInitLocalIpOptions(&instance.config.localIP);
|
||||
ffInitLocaleOptions(&instance.config.locale);
|
||||
ffInitMediaOptions(&instance.config.media);
|
||||
ffInitMemoryOptions(&instance.config.memory);
|
||||
ffInitMonitorOptions(&instance.config.monitor);
|
||||
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);
|
||||
|
||||
ffStrbufInit(&instance.config.libPCI);
|
||||
ffStrbufInit(&instance.config.libVulkan);
|
||||
ffStrbufInit(&instance.config.libWayland);
|
||||
ffStrbufInit(&instance.config.libXcbRandr);
|
||||
ffStrbufInit(&instance.config.libXcb);
|
||||
ffStrbufInit(&instance.config.libXrandr);
|
||||
ffStrbufInit(&instance.config.libX11);
|
||||
ffStrbufInit(&instance.config.libGIO);
|
||||
ffStrbufInit(&instance.config.libDConf);
|
||||
ffStrbufInit(&instance.config.libDBus);
|
||||
ffStrbufInit(&instance.config.libXFConf);
|
||||
ffStrbufInit(&instance.config.libSQLite3);
|
||||
ffStrbufInit(&instance.config.librpm);
|
||||
ffStrbufInit(&instance.config.libImageMagick);
|
||||
ffStrbufInit(&instance.config.libZ);
|
||||
ffStrbufInit(&instance.config.libChafa);
|
||||
ffStrbufInit(&instance.config.libEGL);
|
||||
ffStrbufInit(&instance.config.libGLX);
|
||||
ffStrbufInit(&instance.config.libOSMesa);
|
||||
ffStrbufInit(&instance.config.libOpenCL);
|
||||
ffStrbufInit(&instance.config.libfreetype);
|
||||
ffStrbufInit(&instance.config.libPulse);
|
||||
ffStrbufInit(&instance.config.libnm);
|
||||
ffStrbufInit(&instance.config.libDdcutil);
|
||||
ffOptionsInitLogo(&instance.config.logo);
|
||||
ffOptionsInitGeneral(&instance.config.general);
|
||||
ffOptionsInitModules(&instance.config.modules);
|
||||
ffOptionsInitDisplay(&instance.config.display);
|
||||
ffOptionsInitLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
void ffInitInstance(void)
|
||||
@@ -171,29 +51,6 @@ void ffInitInstance(void)
|
||||
defaultConfig();
|
||||
}
|
||||
|
||||
#if defined(FF_HAVE_THREADS) && !(defined(__APPLE__) || defined(_WIN32) || defined(__ANDROID__))
|
||||
|
||||
#include "detection/gtk_qt/gtk_qt.h"
|
||||
|
||||
#define FF_START_DETECTION_THREADS
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffConnectDisplayServer)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectQt)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK2)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK3)
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(ffDetectGTK4)
|
||||
|
||||
void startDetectionThreads(void)
|
||||
{
|
||||
ffThreadDetach(ffThreadCreate(ffConnectDisplayServerThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectQtThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK2ThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK3ThreadMain, NULL));
|
||||
ffThreadDetach(ffThreadCreate(ffDetectGTK4ThreadMain, NULL));
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_THREADS
|
||||
|
||||
static volatile bool ffDisableLinewrap = true;
|
||||
static volatile bool ffHideCursor = true;
|
||||
|
||||
@@ -229,15 +86,15 @@ static void exitSignalHandler(int signal)
|
||||
void ffStart(void)
|
||||
{
|
||||
#ifdef FF_START_DETECTION_THREADS
|
||||
if(instance.config.multithreading)
|
||||
if(instance.config.general.multithreading)
|
||||
startDetectionThreads();
|
||||
#endif
|
||||
|
||||
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe;
|
||||
ffHideCursor = instance.config.hideCursor && !instance.config.pipe;
|
||||
ffDisableLinewrap = instance.config.display.disableLinewrap && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!instance.config.noBuffer) setvbuf(stdout, NULL, _IOFBF, 4096);
|
||||
setvbuf(stdout, NULL, _IOFBF, instance.config.display.noBuffer ? 0 : 4096);
|
||||
SetConsoleCtrlHandler(consoleHandler, TRUE);
|
||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD mode = 0;
|
||||
@@ -245,7 +102,7 @@ void ffStart(void)
|
||||
SetConsoleMode(hStdout, mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#else
|
||||
if (instance.config.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
|
||||
if (instance.config.display.noBuffer) setvbuf(stdout, NULL, _IONBF, 0);
|
||||
struct sigaction action = { .sa_handler = exitSignalHandler };
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
@@ -253,7 +110,7 @@ void ffStart(void)
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe && !instance.state.resultDoc)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
if(ffHideCursor)
|
||||
@@ -275,105 +132,19 @@ void ffFinish(void)
|
||||
|
||||
static void destroyConfig(void)
|
||||
{
|
||||
ffDestroyLogoOptions(&instance.config.logo);
|
||||
|
||||
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
|
||||
|
||||
ffDestroyBatteryOptions(&instance.config.battery);
|
||||
ffDestroyBiosOptions(&instance.config.bios);
|
||||
ffDestroyBluetoothOptions(&instance.config.bluetooth);
|
||||
ffDestroyBoardOptions(&instance.config.board);
|
||||
ffDestroyBreakOptions(&instance.config.break_);
|
||||
ffDestroyBrightnessOptions(&instance.config.brightness);
|
||||
ffDestroyCPUOptions(&instance.config.cpu);
|
||||
ffDestroyCPUUsageOptions(&instance.config.cpuUsage);
|
||||
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);
|
||||
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);
|
||||
ffDestroyLocalIpOptions(&instance.config.localIP);
|
||||
ffDestroyLocaleOptions(&instance.config.locale);
|
||||
ffDestroyMediaOptions(&instance.config.media);
|
||||
ffDestroyMemoryOptions(&instance.config.memory);
|
||||
ffDestroyMonitorOptions(&instance.config.monitor);
|
||||
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);
|
||||
|
||||
ffStrbufDestroy(&instance.config.libPCI);
|
||||
ffStrbufDestroy(&instance.config.libVulkan);
|
||||
ffStrbufDestroy(&instance.config.libWayland);
|
||||
ffStrbufDestroy(&instance.config.libXcbRandr);
|
||||
ffStrbufDestroy(&instance.config.libXcb);
|
||||
ffStrbufDestroy(&instance.config.libXrandr);
|
||||
ffStrbufDestroy(&instance.config.libX11);
|
||||
ffStrbufDestroy(&instance.config.libGIO);
|
||||
ffStrbufDestroy(&instance.config.libDConf);
|
||||
ffStrbufDestroy(&instance.config.libDBus);
|
||||
ffStrbufDestroy(&instance.config.libXFConf);
|
||||
ffStrbufDestroy(&instance.config.libSQLite3);
|
||||
ffStrbufDestroy(&instance.config.librpm);
|
||||
ffStrbufDestroy(&instance.config.libImageMagick);
|
||||
ffStrbufDestroy(&instance.config.libZ);
|
||||
ffStrbufDestroy(&instance.config.libChafa);
|
||||
ffStrbufDestroy(&instance.config.libEGL);
|
||||
ffStrbufDestroy(&instance.config.libGLX);
|
||||
ffStrbufDestroy(&instance.config.libOSMesa);
|
||||
ffStrbufDestroy(&instance.config.libOpenCL);
|
||||
ffStrbufDestroy(&instance.config.libfreetype);
|
||||
ffStrbufDestroy(&instance.config.libPulse);
|
||||
ffStrbufDestroy(&instance.config.libnm);
|
||||
ffStrbufDestroy(&instance.config.libDdcutil);
|
||||
ffOptionsDestroyLogo(&instance.config.logo);
|
||||
ffOptionsDestroyGeneral(&instance.config.general);
|
||||
ffOptionsDestroyModules(&instance.config.modules);
|
||||
ffOptionsDestroyDisplay(&instance.config.display);
|
||||
ffOptionsDestroyLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
static void destroyState(void)
|
||||
{
|
||||
ffPlatformDestroy(&instance.state.platform);
|
||||
yyjson_doc_free(instance.state.configDoc);
|
||||
yyjson_mut_doc_free(instance.state.resultDoc);
|
||||
ffStrbufDestroy(&instance.state.migrateConfigPath);
|
||||
}
|
||||
|
||||
void ffDestroyInstance(void)
|
||||
@@ -464,6 +235,9 @@ void ffListFeatures(void)
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
"libddcutil\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
"Directx Headers\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
+78
-281
@@ -35,6 +35,18 @@ bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs*
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs)
|
||||
{
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->key, &moduleArgs->key))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "key", &moduleArgs->key);
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->outputFormat, &moduleArgs->outputFormat))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "format", &moduleArgs->outputFormat);
|
||||
if (!ffStrbufEqual(&defaultModuleArgs->keyColor, &moduleArgs->keyColor))
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "keyColor", &moduleArgs->keyColor);
|
||||
if (moduleArgs->keyWidth != defaultModuleArgs->keyWidth)
|
||||
yyjson_mut_obj_add_uint(doc, module, "keyWidth", moduleArgs->keyWidth);
|
||||
}
|
||||
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[])
|
||||
{
|
||||
if (yyjson_is_int(val))
|
||||
@@ -70,7 +82,17 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p
|
||||
return "Invalid enum value type; must be a string or integer";
|
||||
}
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
|
||||
static inline void genJsonResult(FFModuleBaseInfo* baseInfo, yyjson_mut_doc* doc)
|
||||
{
|
||||
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
|
||||
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
|
||||
if (baseInfo->generateJsonResult)
|
||||
baseInfo->generateJsonResult(baseInfo, doc, module);
|
||||
else
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
|
||||
}
|
||||
|
||||
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
if(!isalpha(type[0])) return false;
|
||||
|
||||
@@ -80,7 +102,10 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
|
||||
if (ffStrEqualsIgnCase(type, baseInfo->name))
|
||||
{
|
||||
if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal);
|
||||
baseInfo->printModule(baseInfo);
|
||||
if (__builtin_expect(jsonDoc != NULL, false))
|
||||
genJsonResult(baseInfo, jsonDoc);
|
||||
else
|
||||
baseInfo->printModule(baseInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -97,26 +122,42 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
ffPrepareCPUUsage();
|
||||
break;
|
||||
}
|
||||
case 'd': case 'D': {
|
||||
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
|
||||
{
|
||||
if (module) cfg->modules.diskIo.moduleInfo.parseJsonObject(&cfg->modules.diskIo, module);
|
||||
ffPrepareDiskIO(&cfg->modules.diskIo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'n': case 'N': {
|
||||
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME))
|
||||
{
|
||||
if (module) cfg->modules.netIo.moduleInfo.parseJsonObject(&cfg->modules.netIo, module);
|
||||
ffPrepareNetIO(&cfg->modules.netIo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p': case 'P': {
|
||||
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParsePublicIpJsonObject(&cfg->publicIP, module);
|
||||
ffPreparePublicIp(&cfg->publicIP);
|
||||
if (module) cfg->modules.publicIP.moduleInfo.parseJsonObject(&cfg->modules.publicIP, module);
|
||||
ffPreparePublicIp(&cfg->modules.publicIP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'w': case 'W': {
|
||||
if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME))
|
||||
{
|
||||
if (module) ffParseWeatherJsonObject(&cfg->weather, module);
|
||||
ffPrepareWeather(&cfg->weather);
|
||||
if (module) cfg->modules.weather.moduleInfo.parseJsonObject(&cfg->modules.weather, module);
|
||||
ffPrepareWeather(&cfg->modules.weather);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare)
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
@@ -133,7 +174,7 @@ static const char* printJsonConfig(bool prepare)
|
||||
yyjson_arr_foreach(modules, idx, max, item)
|
||||
{
|
||||
uint64_t ms = 0;
|
||||
if(!prepare && instance.config.stat)
|
||||
if(!prepare && instance.config.display.stat)
|
||||
ms = ffTimeGetTick();
|
||||
|
||||
yyjson_val* module = item;
|
||||
@@ -152,292 +193,48 @@ static const char* printJsonConfig(bool prepare)
|
||||
|
||||
if(prepare)
|
||||
prepareModuleJsonObject(type, module);
|
||||
else if(!parseModuleJsonObject(type, module))
|
||||
else if(!parseModuleJsonObject(type, module, jsonDoc))
|
||||
return "Unknown module type";
|
||||
|
||||
if(!prepare && instance.config.stat)
|
||||
if(!prepare && instance.config.display.stat)
|
||||
{
|
||||
char str[32];
|
||||
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
|
||||
if(instance.config.pipe)
|
||||
puts(str);
|
||||
ms = ffTimeGetTick() - ms;
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
|
||||
yyjson_mut_obj_add_uint(jsonDoc, 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.display.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.display.noBuffer && !jsonDoc) fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseGeneralJsonConfig(void)
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "general");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'general' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "allowSlowOperations"))
|
||||
config->allowSlowOperations = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "thread") || ffStrEqualsIgnCase(key, "multithreading"))
|
||||
config->multithreading = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "stat"))
|
||||
{
|
||||
if ((config->stat = yyjson_get_bool(val)))
|
||||
config->showErrors = true;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "escapeBedrock"))
|
||||
config->escapeBedrock = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "pipe"))
|
||||
config->pipe = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "processingTimeout"))
|
||||
config->processingTimeout = (int32_t) yyjson_get_int(val);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
else if (ffStrEqualsIgnCase(key, "playerName"))
|
||||
ffStrbufSetS(&config->playerName, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osFile"))
|
||||
ffStrbufSetS(&config->osFile, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dsForceDrm"))
|
||||
config->dsForceDrm = yyjson_get_bool(val);
|
||||
#elif defined(_WIN32)
|
||||
else if (ffStrEqualsIgnCase(key, "wmiTimeout"))
|
||||
config->wmiTimeout = (int32_t) yyjson_get_int(val);
|
||||
#endif
|
||||
|
||||
else
|
||||
return "Unknown general property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseDisplayJsonConfig(void)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "display");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'display' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "showErrors"))
|
||||
config->showErrors = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "disableLinewrap"))
|
||||
config->disableLinewrap = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "hideCursor"))
|
||||
config->hideCursor = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "separator"))
|
||||
ffStrbufSetS(&config->keyValueSeparator, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "color"))
|
||||
{
|
||||
if (yyjson_is_str(val))
|
||||
{
|
||||
ffOptionParseColor(yyjson_get_str(val), &config->colorKeys);
|
||||
ffStrbufSet(&config->colorTitle, &config->colorKeys);
|
||||
}
|
||||
else if (yyjson_is_obj(val))
|
||||
{
|
||||
const char* colorKeys = yyjson_get_str(yyjson_obj_get(val, "keys"));
|
||||
if (colorKeys)
|
||||
ffOptionParseColor(colorKeys, &config->colorKeys);
|
||||
const char* colorTitle = yyjson_get_str(yyjson_obj_get(val, "title"));
|
||||
if (colorTitle)
|
||||
ffOptionParseColor(colorTitle, &config->colorTitle);
|
||||
}
|
||||
else
|
||||
return "display.color must be either a string or an object";
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "brightColor"))
|
||||
config->brightColor = yyjson_get_bool(val);
|
||||
else if (ffStrEqualsIgnCase(key, "binaryPrefix"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "iec", FF_BINARY_PREFIX_TYPE_IEC },
|
||||
{ "si", FF_BINARY_PREFIX_TYPE_SI },
|
||||
{ "jedec", FF_BINARY_PREFIX_TYPE_JEDEC },
|
||||
{},
|
||||
});
|
||||
if (error) return error;
|
||||
config->binaryPrefixType = (FFBinaryPrefixType) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "sizeNdigits"))
|
||||
config->sizeNdigits = (uint8_t) yyjson_get_uint(val);
|
||||
else if (ffStrEqualsIgnCase(key, "sizeMaxPrefix"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "B", 0 },
|
||||
{ "kB", 1 },
|
||||
{ "MB", 2 },
|
||||
{ "GB", 3 },
|
||||
{ "TB", 4 },
|
||||
{ "PB", 5 },
|
||||
{ "EB", 6 },
|
||||
{ "ZB", 7 },
|
||||
{ "YB", 8 },
|
||||
{}
|
||||
});
|
||||
if (error) return error;
|
||||
config->sizeMaxPrefix = (uint8_t) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "temperatureUnit"))
|
||||
{
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "CELSIUS", FF_TEMPERATURE_UNIT_CELSIUS },
|
||||
{ "C", FF_TEMPERATURE_UNIT_CELSIUS },
|
||||
{ "FAHRENHEIT", FF_TEMPERATURE_UNIT_FAHRENHEIT },
|
||||
{ "F", FF_TEMPERATURE_UNIT_FAHRENHEIT },
|
||||
{ "KELVIN", FF_TEMPERATURE_UNIT_KELVIN },
|
||||
{ "K", FF_TEMPERATURE_UNIT_KELVIN },
|
||||
{},
|
||||
});
|
||||
if (error) return error;
|
||||
config->temperatureUnit = (FFTemperatureUnit) value;
|
||||
}
|
||||
else if (ffStrEqualsIgnCase(key, "percentType"))
|
||||
config->percentType = (uint32_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";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffParseLibraryJsonConfig(void)
|
||||
{
|
||||
FFconfig* config = &instance.config;
|
||||
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
assert(root);
|
||||
|
||||
if (!yyjson_is_obj(root))
|
||||
return "Invalid JSON config format. Root value must be an object";
|
||||
|
||||
yyjson_val* object = yyjson_obj_get(root, "library");
|
||||
if (!object) return NULL;
|
||||
if (!yyjson_is_obj(object)) return "Property 'library' must be an object";
|
||||
|
||||
yyjson_val *key_, *val;
|
||||
size_t idx, max;
|
||||
yyjson_obj_foreach(object, idx, max, key_, val)
|
||||
{
|
||||
const char* key = yyjson_get_str(key_);
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "pci"))
|
||||
ffStrbufSetS(&config->libPCI, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "vulkan"))
|
||||
ffStrbufSetS(&config->libVulkan, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "freetype"))
|
||||
ffStrbufSetS(&config->libfreetype, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "wayland"))
|
||||
ffStrbufSetS(&config->libWayland, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "xcbRandr"))
|
||||
ffStrbufSetS(&config->libXcbRandr, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "xcb"))
|
||||
ffStrbufSetS(&config->libXcb, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "Xrandr"))
|
||||
ffStrbufSetS(&config->libXrandr, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "X11"))
|
||||
ffStrbufSetS(&config->libX11, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "gio"))
|
||||
ffStrbufSetS(&config->libGIO, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "DConf"))
|
||||
ffStrbufSetS(&config->libDConf, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "dbus"))
|
||||
ffStrbufSetS(&config->libDBus, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "XFConf"))
|
||||
ffStrbufSetS(&config->libXFConf, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "sqlite") || ffStrEqualsIgnCase(key, "sqlite3"))
|
||||
ffStrbufSetS(&config->libSQLite3, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "rpm"))
|
||||
ffStrbufSetS(&config->librpm, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "imagemagick"))
|
||||
ffStrbufSetS(&config->libImageMagick, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "z"))
|
||||
ffStrbufSetS(&config->libZ, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "chafa"))
|
||||
ffStrbufSetS(&config->libChafa, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "egl"))
|
||||
ffStrbufSetS(&config->libEGL, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "glx"))
|
||||
ffStrbufSetS(&config->libGLX, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "osmesa"))
|
||||
ffStrbufSetS(&config->libOSMesa, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "opencl"))
|
||||
ffStrbufSetS(&config->libOpenCL, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "pulse"))
|
||||
ffStrbufSetS(&config->libPulse, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "nm"))
|
||||
ffStrbufSetS(&config->libnm, yyjson_get_str(val));
|
||||
else if (ffStrEqualsIgnCase(key, "ddcutil"))
|
||||
ffStrbufSetS(&config->libDdcutil, yyjson_get_str(val));
|
||||
else
|
||||
return "Unknown library property";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ffPrintJsonConfig(bool prepare)
|
||||
{
|
||||
const char* error = printJsonConfig(prepare);
|
||||
const char* error = printJsonConfig(prepare, jsonDoc);
|
||||
if (error)
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
{
|
||||
if (jsonDoc)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_obj(jsonDoc);
|
||||
yyjson_mut_obj_add_str(jsonDoc, obj, "error", error);
|
||||
yyjson_mut_doc_set_root(jsonDoc, obj);
|
||||
}
|
||||
else
|
||||
ffPrintErrorString("JsonConfig", 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-4
@@ -4,7 +4,22 @@
|
||||
|
||||
bool ffJsonConfigParseModuleArgs(const char* key, yyjson_val* val, FFModuleArgs* moduleArgs);
|
||||
const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair pairs[]);
|
||||
void ffPrintJsonConfig(bool prepare);
|
||||
const char* ffParseGeneralJsonConfig(void);
|
||||
const char* ffParseDisplayJsonConfig(void);
|
||||
const char* ffParseLibraryJsonConfig(void);
|
||||
void ffPrintJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc);
|
||||
void ffJsonConfigGenerateModuleArgsConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFModuleArgs* defaultModuleArgs, FFModuleArgs* moduleArgs);
|
||||
|
||||
yyjson_api_inline yyjson_mut_val* yyjson_mut_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) {
|
||||
return yyjson_mut_strncpy(doc, buf->chars, buf->length);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
+57
-55
@@ -5,31 +5,32 @@ static FFModuleBaseInfo* A[] = {
|
||||
};
|
||||
|
||||
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,
|
||||
(void*) &instance.config.modules.battery,
|
||||
(void*) &instance.config.modules.bios,
|
||||
(void*) &instance.config.modules.bluetooth,
|
||||
(void*) &instance.config.modules.board,
|
||||
(void*) &instance.config.modules.break_,
|
||||
(void*) &instance.config.modules.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,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
(void*) &instance.config.modules.cpu,
|
||||
(void*) &instance.config.modules.cpuUsage,
|
||||
(void*) &instance.config.modules.cursor,
|
||||
(void*) &instance.config.modules.custom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* D[] = {
|
||||
(void*) &instance.config.dateTime,
|
||||
(void*) &instance.config.de,
|
||||
(void*) &instance.config.display,
|
||||
(void*) &instance.config.disk,
|
||||
(void*) &instance.config.modules.dateTime,
|
||||
(void*) &instance.config.modules.de,
|
||||
(void*) &instance.config.modules.display,
|
||||
(void*) &instance.config.modules.disk,
|
||||
(void*) &instance.config.modules.diskIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -38,23 +39,23 @@ static FFModuleBaseInfo* E[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* F[] = {
|
||||
(void*) &instance.config.font,
|
||||
(void*) &instance.config.modules.font,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* G[] = {
|
||||
(void*) &instance.config.gamepad,
|
||||
(void*) &instance.config.gpu,
|
||||
(void*) &instance.config.modules.gamepad,
|
||||
(void*) &instance.config.modules.gpu,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* H[] = {
|
||||
(void*) &instance.config.host,
|
||||
(void*) &instance.config.modules.host,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* I[] = {
|
||||
(void*) &instance.config.icons,
|
||||
(void*) &instance.config.modules.icons,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -63,41 +64,42 @@ static FFModuleBaseInfo* J[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* K[] = {
|
||||
(void*) &instance.config.kernel,
|
||||
(void*) &instance.config.modules.kernel,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* L[] = {
|
||||
(void*) &instance.config.lm,
|
||||
(void*) &instance.config.locale,
|
||||
(void*) &instance.config.localIP,
|
||||
(void*) &instance.config.modules.lm,
|
||||
(void*) &instance.config.modules.locale,
|
||||
(void*) &instance.config.modules.localIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* M[] = {
|
||||
(void*) &instance.config.media,
|
||||
(void*) &instance.config.memory,
|
||||
(void*) &instance.config.monitor,
|
||||
(void*) &instance.config.modules.media,
|
||||
(void*) &instance.config.modules.memory,
|
||||
(void*) &instance.config.modules.monitor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* N[] = {
|
||||
(void*) &instance.config.modules.netIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* O[] = {
|
||||
(void*) &instance.config.openCL,
|
||||
(void*) &instance.config.openGL,
|
||||
(void*) &instance.config.os,
|
||||
(void*) &instance.config.modules.openCL,
|
||||
(void*) &instance.config.modules.openGL,
|
||||
(void*) &instance.config.modules.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,
|
||||
(void*) &instance.config.modules.packages,
|
||||
(void*) &instance.config.modules.player,
|
||||
(void*) &instance.config.modules.powerAdapter,
|
||||
(void*) &instance.config.modules.processes,
|
||||
(void*) &instance.config.modules.publicIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -110,40 +112,40 @@ static FFModuleBaseInfo* R[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* S[] = {
|
||||
(void*) &instance.config.separator,
|
||||
(void*) &instance.config.shell,
|
||||
(void*) &instance.config.sound,
|
||||
(void*) &instance.config.swap,
|
||||
(void*) &instance.config.modules.separator,
|
||||
(void*) &instance.config.modules.shell,
|
||||
(void*) &instance.config.modules.sound,
|
||||
(void*) &instance.config.modules.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,
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* U[] = {
|
||||
(void*) &instance.config.uptime,
|
||||
(void*) &instance.config.users,
|
||||
(void*) &instance.config.modules.uptime,
|
||||
(void*) &instance.config.modules.users,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* V[] = {
|
||||
(void*) &instance.config.version,
|
||||
(void*) &instance.config.vulkan,
|
||||
(void*) &instance.config.modules.version,
|
||||
(void*) &instance.config.modules.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,
|
||||
(void*) &instance.config.modules.wallpaper,
|
||||
(void*) &instance.config.modules.weather,
|
||||
(void*) &instance.config.modules.wm,
|
||||
(void*) &instance.config.modules.wifi,
|
||||
(void*) &instance.config.modules.wmTheme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -3,14 +3,23 @@
|
||||
#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 (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
void (*printHelpFormat)(void);
|
||||
void (*generateJsonConfig)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* obj);
|
||||
} FFModuleBaseInfo;
|
||||
|
||||
static inline void ffOptionInitModuleBaseInfo(
|
||||
@@ -18,13 +27,19 @@ static inline void ffOptionInitModuleBaseInfo(
|
||||
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* printModule, // void (*const printModule)(void* options)
|
||||
void* generateJsonResult, // void (*const generateJsonResult)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
void (*printHelpFormat)(void),
|
||||
void* generateJsonConfig // void (*const generateJsonConfig)(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->generateJsonResult = (__typeof__(baseInfo->generateJsonResult)) generateJsonResult;
|
||||
baseInfo->printHelpFormat = printHelpFormat;
|
||||
baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig;
|
||||
}
|
||||
|
||||
typedef struct FFModuleArgs
|
||||
|
||||
@@ -65,7 +65,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
double size = (double) bytes;
|
||||
uint8_t counter = 0;
|
||||
|
||||
while(size >= base && counter < instance.config.sizeMaxPrefix && prefixes[counter + 1])
|
||||
while(size >= base && counter < instance.config.display.sizeMaxPrefix && prefixes[counter + 1])
|
||||
{
|
||||
size /= base;
|
||||
counter++;
|
||||
@@ -74,12 +74,12 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
if(counter == 0)
|
||||
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
|
||||
else
|
||||
ffStrbufAppendF(result, "%.*f %s", instance.config.sizeNdigits, size, prefixes[counter]);
|
||||
ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]);
|
||||
}
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result)
|
||||
{
|
||||
switch (instance.config.binaryPrefixType)
|
||||
switch (instance.config.display.binaryPrefixType)
|
||||
{
|
||||
case FF_BINARY_PREFIX_TYPE_IEC:
|
||||
parseSize(result, bytes, 1024, (const char*[]) {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", NULL});
|
||||
@@ -98,7 +98,7 @@ void ffParseSize(uint64_t bytes, FFstrbuf* result)
|
||||
|
||||
void ffParseTemperature(double celsius, FFstrbuf* buffer)
|
||||
{
|
||||
switch (instance.config.temperatureUnit)
|
||||
switch (instance.config.display.temperatureUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.1f°C", celsius);
|
||||
|
||||
+31
-14
@@ -10,16 +10,20 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
if(moduleName == NULL)
|
||||
return;
|
||||
|
||||
if(!instance.config.pipe)
|
||||
//This is used as a magic value for hiding keys
|
||||
if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " "))
|
||||
return;
|
||||
|
||||
if(!instance.config.display.pipe)
|
||||
{
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
if (instance.config.brightColor)
|
||||
if (instance.config.display.brightColor)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout);
|
||||
|
||||
if(moduleArgs && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR) && moduleArgs->keyColor.length > 0)
|
||||
ffPrintColor(&moduleArgs->keyColor);
|
||||
else
|
||||
ffPrintColor(&instance.config.colorKeys);
|
||||
ffPrintColor(&instance.config.display.colorKeys);
|
||||
}
|
||||
|
||||
//NULL check is required for modules with custom keys, e.g. disk with the folder path
|
||||
@@ -39,18 +43,18 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
}
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
ffStrbufWriteTo(&instance.config.keyValueSeparator, stdout);
|
||||
ffStrbufWriteTo(&instance.config.display.keyValueSeparator, stdout);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
|
||||
if (!instance.config.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
|
||||
if (!instance.config.display.pipe && !(printType & FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH))
|
||||
{
|
||||
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.keyWidth;
|
||||
uint32_t keyWidth = moduleArgs && moduleArgs->keyWidth > 0 ? moduleArgs->keyWidth : instance.config.display.keyWidth;
|
||||
if (keyWidth > 0)
|
||||
printf("\e[%uG", (unsigned) (keyWidth + instance.state.logoWidth));
|
||||
}
|
||||
@@ -73,17 +77,17 @@ void ffPrintFormatString(const char* moduleName, uint8_t moduleIndex, const FFMo
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
{
|
||||
if(!instance.config.showErrors)
|
||||
if(!instance.config.display.showErrors)
|
||||
return;
|
||||
|
||||
ffPrintLogoAndKey(moduleName, moduleIndex, moduleArgs, printType);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
|
||||
vprintf(message, arguments);
|
||||
|
||||
if(!instance.config.pipe)
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
|
||||
putchar('\n');
|
||||
@@ -112,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)
|
||||
@@ -130,3 +132,18 @@ void ffPrintCharTimes(char c, uint32_t times)
|
||||
if(remaining > 0)
|
||||
fwrite(str, 1, remaining, stdout);
|
||||
}
|
||||
|
||||
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[])
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(name);
|
||||
ffStrbufLowerCase(&buffer);
|
||||
printf("--%s-format:\n", buffer.chars);
|
||||
printf("Sets the format string for %s output.\n", name);
|
||||
puts("To see how a format string is constructed, take a look at \"fastfetch --help format\".");
|
||||
puts("The following values are passed:");
|
||||
|
||||
for(unsigned i = 0; i < numArgs; i++)
|
||||
printf(" {%u}: %s\n", i + 1, args[i]);
|
||||
|
||||
printf("The default is something similar to \"%s\".\n", def);
|
||||
}
|
||||
|
||||
@@ -25,4 +25,6 @@ FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex,
|
||||
void ffPrintColor(const FFstrbuf* colorValue);
|
||||
void ffPrintCharTimes(char c, uint32_t times);
|
||||
|
||||
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,10 +34,12 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
//Child
|
||||
if(childPid == 0)
|
||||
{
|
||||
int nullFile = open("/dev/null", O_WRONLY);
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
close(useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
setenv("LANG", "C", 1);
|
||||
execvp(argv[0], argv);
|
||||
exit(901);
|
||||
}
|
||||
@@ -47,7 +49,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
if (timeout >= 0)
|
||||
fcntl(childPipeFd, F_SETFL, fcntl(childPipeFd, F_GETFL) | O_NONBLOCK);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ enum { FF_PIPE_BUFSIZ = 4096 };
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int timeout = instance.config.processingTimeout;
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
L"\\\\.\\pipe\\LOCAL\\",
|
||||
|
||||
+4
-11
@@ -15,18 +15,14 @@ typedef enum FFInitState
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_INIT(dataObject, userLibraryName, ...) \
|
||||
static dataObject data; \
|
||||
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; \
|
||||
static FFInitState initState = FF_INITSTATE_UNINITIALIZED; \
|
||||
ffThreadMutexLock(&mutex); \
|
||||
if(initState != FF_INITSTATE_UNINITIALIZED) {\
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return initState == FF_INITSTATE_SUCCESSFUL ? &data : NULL; \
|
||||
} \
|
||||
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||
void* libraryHandle = ffLibraryLoad(&userLibraryName, __VA_ARGS__, NULL); \
|
||||
if(libraryHandle == NULL) { \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
} \
|
||||
|
||||
@@ -35,20 +31,17 @@ typedef enum FFInitState
|
||||
if(data.ff ## symbolName == NULL) { \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_RETURN \
|
||||
initState = FF_INITSTATE_SUCCESSFUL; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return &data;
|
||||
|
||||
#define FF_LIBRARY_DATA_LOAD_ERROR \
|
||||
{ \
|
||||
dlclose(libraryHandle); \
|
||||
initState = FF_INITSTATE_FAILED; \
|
||||
ffThreadMutexUnlock(&mutex); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
@@ -99,7 +92,7 @@ typedef struct GSettingsData
|
||||
|
||||
static const GSettingsData* getGSettingsData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(GSettingsData, instance.config.library.libGIO, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_source_lookup)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(g_settings_schema_has_key)
|
||||
@@ -172,7 +165,7 @@ typedef struct DConfData
|
||||
|
||||
static const DConfData* getDConfData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(DConfData, instance.config.library.libDConf, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_read_full)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(dconf_client_new)
|
||||
@@ -243,7 +236,7 @@ typedef struct XFConfData
|
||||
|
||||
static const XFConfData* getXFConfData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(XFConfData, instance.config.library.libXFConf, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_get)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(xfconf_channel_has_property)
|
||||
@@ -305,7 +298,7 @@ typedef struct SQLiteData
|
||||
|
||||
static const SQLiteData* getSQLiteData(void)
|
||||
{
|
||||
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_DATA_LOAD_INIT(SQLiteData, instance.config.library.libSQLite3, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_open_v2)
|
||||
FF_LIBRARY_DATA_LOAD_SYMBOL(sqlite3_prepare_v2)
|
||||
|
||||
+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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# This file sets the default config for all users of the system.
|
||||
|
||||
# For more information about how configuration files work,
|
||||
# see ~/.config/fastfetch/config.conf, generated during first run.
|
||||
# see ~/.config/fastfetch/config.conf.
|
||||
# All options that can be put there (or passed as argument) can be put here too.
|
||||
|
||||
# Use fastfetch --print-config-system > /etc/fastfetch/config.conf
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"percentType": 9 // colored percent number
|
||||
"percent": {
|
||||
"type": 9
|
||||
} // colored percent number
|
||||
},
|
||||
"modules": [
|
||||
"title",
|
||||
|
||||
@@ -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,6 +370,7 @@
|
||||
#--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
|
||||
@@ -391,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
|
||||
@@ -411,7 +413,7 @@
|
||||
#--terminal-format
|
||||
#--terminalfont-format
|
||||
#--cpu-format
|
||||
#--cpu-usage-format
|
||||
#--cpuusage-format
|
||||
#--gpu-format
|
||||
#--memory-format
|
||||
#--swap-format
|
||||
@@ -421,6 +423,7 @@
|
||||
#--lm-format
|
||||
#--locale-format
|
||||
#--localip-format
|
||||
#--netio-format
|
||||
#--publicip-format
|
||||
#--weather-format
|
||||
#--monitor-format
|
||||
@@ -439,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
|
||||
@@ -459,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
|
||||
@@ -469,6 +473,7 @@
|
||||
#--lm-key-color
|
||||
#--locale-key-color
|
||||
#--localip-key-color
|
||||
#--netio-key-color
|
||||
#--publicip-key-color
|
||||
#--weather-key-color
|
||||
#--monitor-key-color
|
||||
|
||||
+81
-60
@@ -1,9 +1,11 @@
|
||||
Usage: fastfetch <options>
|
||||
Fastfetch is a neofetch-like tool for fetching system information and displaying them in a pretty way
|
||||
|
||||
Usage: fastfetch <?options>
|
||||
|
||||
Informative options:
|
||||
-h,--help: Show this message
|
||||
-h,--help <command>: Show help for a specific command
|
||||
-v,--version: Show the version of fastfetch
|
||||
-h, --help: Show this message
|
||||
-h, --help <command>: Show help for a specific command
|
||||
-v, --version: Show the version of fastfetch
|
||||
--list-config-paths: List search paths of config files
|
||||
--list-data-paths: List search paths of presets and logos
|
||||
--list-logos: List available logos
|
||||
@@ -14,22 +16,22 @@ Informative options:
|
||||
--print-config-system: Print the default system config
|
||||
--print-config-user: Print the default user config
|
||||
--print-structure: Print the default structure
|
||||
--gen-config <?type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or `conf`
|
||||
--gen-config-force <?type>: Generate a sample config file in the default path. Overwrite the existing one
|
||||
|
||||
Config options:
|
||||
-c, --load-config <file>: Load a config file or preset (+)
|
||||
--gen-config <type>: Generate a sample config file in the default path. Param `type` can be `jsonc` or deprecated `conf`
|
||||
--gen-config-force <type>: Generate a sample config file in the default path. Overwrite the existing one
|
||||
--migrate-config <?path>: Migrate old flag based config file to new JSONC format. Optional param `path` is the file path that new file should be write to
|
||||
|
||||
General options:
|
||||
--load-config <file>: Load a config file or preset (+)
|
||||
--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
|
||||
--thread <?value>: Use separate threads to send HTTP requests
|
||||
--escape-bedrock <?value>: On Bedrock Linux, whether to escape the bedrock jail
|
||||
--pipe <?value>: Disable logo and all escape sequences
|
||||
--wmi-timeout <num>: Set the timeout (ms) for WMI queries. Windows only. Default is 5000
|
||||
--processing-timeout <num>: Set the timeout (ms) when waiting for child processes. Default is 1000
|
||||
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false
|
||||
--ds-force-drm <?value>: Set if only DRM should be used to detect displays. Default is false. Linux only
|
||||
|
||||
Logo options:
|
||||
-l,--logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
|
||||
-l, --logo <logo>: Set the logo; if default, the name of a builtin logo or a path to a file
|
||||
--logo-type <type>: Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa
|
||||
--logo-width <width>: Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||
--logo-height <height>: Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol
|
||||
@@ -40,6 +42,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-separate <?value>: If true, print modules at bottom of the logo
|
||||
--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>
|
||||
@@ -56,7 +59,9 @@ Logo options:
|
||||
--chafa-dither-mode <value>: Set output dither mode (No effect with 24-bit color). This value maps the int value of enum ChafaDitherMode. See chafa document for detail
|
||||
|
||||
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.
|
||||
-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.
|
||||
--stat <?value>: Show time usage (in ms) for individual modules
|
||||
--pipe <?value>: Disable logo and all escape sequences
|
||||
--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
|
||||
@@ -70,6 +75,7 @@ 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
|
||||
@@ -81,8 +87,8 @@ Display options:
|
||||
|
||||
General module options:
|
||||
--<module>-format <format>: Set the format string to use for each specific module.
|
||||
To see how a format string works, use fastfetch --help format.
|
||||
To see help about a specific format string, use fastfetch --help <module>-format.
|
||||
To see how a format string works, use `fastfetch --help format`.
|
||||
To see help about a specific format string, use `fastfetch --help <module>-format`.
|
||||
|
||||
--<module>-key <key>: Set the key to use for each specific module.
|
||||
For modules which print multiple lines, the string is parsed as a format string with the index as first character.
|
||||
@@ -91,68 +97,83 @@ General module options:
|
||||
--<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>
|
||||
--lib-vulkan <path>
|
||||
--lib-wayland <path>
|
||||
--lib-xcb-randr <path>
|
||||
--lib-xcb <path>
|
||||
--lib-Xrandr <path>
|
||||
--lib-X11 <path>
|
||||
--lib-gio <path>
|
||||
--lib-DConf <path>
|
||||
--lib-DBus <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-sqlite3 <path>
|
||||
--lib-rpm <path>
|
||||
--lib-imagemagick <path>
|
||||
--lib-z <path>
|
||||
--lib-chafa <path>
|
||||
--lib-egl <path>
|
||||
--lib-glx <path>
|
||||
--lib-osmesa <path>
|
||||
--lib-opencl <path>
|
||||
--lib-pulse <path>
|
||||
--lib-freetype <path>
|
||||
--lib-ddcutil <path>
|
||||
--lib-PCI <path>: GPU output
|
||||
--lib-vulkan <path>: Vulkan module & fallback for GPU output
|
||||
--lib-wayland <path>: Better display performance and output in wayland sessions
|
||||
--lib-xcb-randr <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-xcb <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-Xrandr <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-X11 <path>: X11 sessions for better display detection and faster WM detection
|
||||
--lib-gio <path>: Needed for values that are only stored GSettings
|
||||
--lib-DConf <path>: Needed for values that are only stored in DConf + Fallback for GSettings
|
||||
--lib-DBus <path>: Bluetooth, Player & Media detection
|
||||
--lib-XFConf <path>: Needed for XFWM theme and XFCE Terminal font
|
||||
--lib-sqlite3 <path>: Needed for pkg & rpm package count
|
||||
--lib-rpm <path>: Slower fallback for rpm package count
|
||||
--lib-imagemagick <path>: Images in terminal using sixel or kitty graphics protocol
|
||||
--lib-z <path>: Libz. Faster image output when using kitty graphics protocol
|
||||
--lib-chafa <path>: Image output as ascii art
|
||||
--lib-egl <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-glx <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-osmesa <path>: Needed by the OpenGL module for gl context creation
|
||||
--lib-opencl <path>: OpenCL module
|
||||
--lib-pulse <path>: Pulseaudio. Used for Sound detection
|
||||
--lib-nm: NetworkManager. Used for Wifi detection
|
||||
--lib-freetype <path>: Used for Termux font detection
|
||||
--lib-ddcutil <path>: Used for brightness detection of external displays
|
||||
|
||||
Module specific options:
|
||||
--title-fqdn <?value>: Set if the title should use fully qualified domain name. Default is false
|
||||
--title-color-user <color>: Set color of the user name (left part). Default is empty (use color of `--color-title`).
|
||||
--title-color-at <color>: Set color of the @ symbol (middle part). Default is empty (use color of `--color-title`)
|
||||
--title-color-host <color>: Set color of the host name (right part). Default is empty (use color of `--color-title`)
|
||||
--chassis-use-wmi <?value>: Set if WMI query should be used on Windows, which detects more information but slower. Default is false
|
||||
--separator-string <str>: Set the string printed by the separator module
|
||||
--os-file <path>: Set the path to the file containing OS information
|
||||
--os-file <path>: Set the path to the file containing OS information. Linux only
|
||||
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
|
||||
--disk-show-regular <?value>: Set if regular volume should be printed. Default is true
|
||||
--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
|
||||
--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
|
||||
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing. Default is true
|
||||
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
|
||||
--disk-use-available <?value>: Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false
|
||||
--diskio-name-prefix <str>: Show disks with given name prefix only. Default is empty
|
||||
--bluetooth-show-disconnected <?value>: Set if disconnected bluetooth devices should be printed. Default is false
|
||||
--packages-winget <?value>: Set if winget package count should be detected. 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
|
||||
--display-precise-refresh-rate <?value>: Set if decimal refresh rates should not be rounded into integers when printing. Default is true
|
||||
--brightness-ddcci-sleep <num>: Set the sleep times (in ms) when sending DDC/CI requests. See <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail. Default is 10
|
||||
--sound-type <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
|
||||
--battery-dir <folder>: The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only
|
||||
--battery-use-setup-api <?value>: Set if `SetupAPI` should be used on Windows to detect battery info, which supports multi batteries, but slower. Windows only
|
||||
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
|
||||
--cpu-freq-ndigits <num>: Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2
|
||||
--cpuusage-separate <?value>: Display CPU usage per CPU logical core, instead of an average result. Default is false
|
||||
--de-slow-version-detection <?value>: Set if DE version should be detected with slow operations. Default is false
|
||||
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
|
||||
--gpu-use-nvml <?value>: Use nvml (NVIDIA Management Library) to detect more detailed GPU information (memory usage, CUDA core count, etc). Default is false
|
||||
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
|
||||
--gpu-hide-type <?value>: Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
|
||||
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
|
||||
--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 true
|
||||
--localip-compact <?value>: Show all IPs in one line. 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 `+`).
|
||||
--weather-timeout: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format: The output weather format to be used. It must be URI encoded.
|
||||
--player-name: The name of the player to use
|
||||
--opengl-library <value>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--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 true
|
||||
--publicip-timeout <num>: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
|
||||
--publicip-url <str>: The URL of public IP detection server to be used.
|
||||
--weather-location <str>: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
|
||||
--weather-timeout <num>: Time in milliseconds to wait for the weather server to respond. Default is disabled (0)
|
||||
--weather-output-format <str>: The output weather format to be used. It must be URI encoded.
|
||||
--wm-detect-plugin <?value>: Set if window manager plugin should be detected on supported platforms. Default is false
|
||||
--player-name <str>: The name of the player to use for module Media and Player. Linux only
|
||||
--opengl-library <str>: Set the OpenGL context creation library to use. Must be auto, egl, glx or osmesa. Default is auto
|
||||
--command-shell <str>: Set the shell program to execute the command text. Default is cmd for Windows, /bin/sh for *nix
|
||||
--command-key <str>: Set the module key to display
|
||||
--command-text <str>: Set the command text to be executed
|
||||
@@ -162,4 +183,4 @@ Module specific options:
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. "true" will be used if not set.
|
||||
A (+) at the end indicates that more help can be printed with --help <option>
|
||||
All options can be made permanent in $XDG_CONFIG_HOME/fastfetch/config.conf
|
||||
All options can be made permanent with command `fastfetch <options> --migrate-config`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
usage: fastfetch --color <color>
|
||||
Usage: fastfetch --color <color>
|
||||
|
||||
<color> must be a color encoding for linux terminals. It is inserted between "ESC[" and "m".
|
||||
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
|
||||
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Examples:
|
||||
--color 35: sets the color to pink
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
usage: fastfetch --load-config <file>
|
||||
Usage: fastfetch -c <file>
|
||||
|
||||
Loads a config file. A config file contains one flag per line. Empty lines or lines starting with # are ignored.
|
||||
If the file is relative it looks in the following order:
|
||||
|
||||
@@ -1 +1 @@
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:PowerAdapter:Locale:Break:Colors
|
||||
Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Locale:Break:Colors
|
||||
|
||||
@@ -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, ", ");
|
||||
|
||||
@@ -17,12 +17,8 @@ static double detectBatteryTemp(void)
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
|
||||
if (matchDict == NULL)
|
||||
return "IOServiceMatching(\"AppleSmartBattery\") failed";
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
io_registry_entry_t registryEntry;
|
||||
@@ -38,7 +34,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");
|
||||
|
||||
@@ -32,7 +32,7 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
if(instance.config.allowSlowOperations)
|
||||
if(options->useSetupApi)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
@@ -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,9 +9,9 @@
|
||||
typedef struct FFBrightnessResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
float value;
|
||||
double min, max, current;
|
||||
} FFBrightnessResult;
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
|
||||
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
#include "brightness.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/apple/ddcci.h"
|
||||
#include "util/edidHelper.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
// DDC/CI
|
||||
#ifdef __aarch64__
|
||||
typedef CFTypeRef IOAVServiceRef;
|
||||
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import));
|
||||
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import));
|
||||
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import));
|
||||
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import));
|
||||
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
|
||||
#else
|
||||
// DDC/CI (Intel)
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
#include <IOKit/i2c/IOI2CInterface.h>
|
||||
extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import));
|
||||
#endif
|
||||
|
||||
// ACPI
|
||||
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
|
||||
|
||||
// Works for internal display
|
||||
@@ -20,7 +38,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);
|
||||
}
|
||||
}
|
||||
@@ -29,19 +49,16 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __aarch64__
|
||||
// https://github.com/waydabber/m1ddc
|
||||
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
|
||||
FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
|
||||
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
|
||||
return "IOAVService is not available";
|
||||
|
||||
CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy");
|
||||
if (matchDict == NULL)
|
||||
return "IOServiceMatching(\"DCPAVServiceProxy\") failed";
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
|
||||
return "IOServiceGetMatchingServices() failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
|
||||
@@ -76,7 +93,7 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
|
||||
for (uint32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn));
|
||||
usleep(10000);
|
||||
usleep(options->ddcciSleep * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +107,9 @@ FF_MAYBE_UNUSED 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] = {};
|
||||
@@ -101,17 +120,80 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available";
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
|
||||
{
|
||||
if (display->type == FF_DISPLAY_TYPE_EXTERNAL)
|
||||
{
|
||||
io_service_t framebuffer = 0;
|
||||
CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer);
|
||||
if (framebuffer == 0) continue;
|
||||
|
||||
IOItemCount count;
|
||||
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue;
|
||||
|
||||
io_service_t interface = 0;
|
||||
if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue;
|
||||
|
||||
uint8_t i2cOut[12] = {};
|
||||
IOI2CConnectRef connect;
|
||||
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
|
||||
{
|
||||
IOObjectRelease(interface);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
|
||||
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
|
||||
|
||||
IOI2CRequest request = {
|
||||
.commFlags = kNilOptions,
|
||||
.sendAddress = 0x6e,
|
||||
.sendTransactionType = kIOI2CSimpleTransactionType,
|
||||
.sendBuffer = (vm_address_t) i2cIn,
|
||||
.sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]),
|
||||
.minReplyDelay = options->ddcciSleep,
|
||||
.replyAddress = 0x6F,
|
||||
.replySubAddress = 0x51,
|
||||
.replyTransactionType = kIOI2CDDCciReplyTransactionType,
|
||||
.replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]),
|
||||
.replyBuffer = (vm_address_t) i2cOut,
|
||||
};
|
||||
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
|
||||
IOI2CInterfaceClose(connect, kNilOptions);
|
||||
IOObjectRelease(interface);
|
||||
|
||||
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue;
|
||||
|
||||
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
|
||||
|
||||
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
|
||||
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
|
||||
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
brightness->max = max;
|
||||
brightness->min = 0;
|
||||
brightness->current = current;
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
|
||||
detectWithDisplayServices(displayServer, result);
|
||||
|
||||
#ifdef __aarch64__
|
||||
if (displayServer->displays.length > result->length)
|
||||
detectWithDdcci(result);
|
||||
#endif
|
||||
detectWithDdcci(displayServer, options, result);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
// https://man.freebsd.org/cgi/man.cgi?query=backlight&sektion=9
|
||||
char path[] = "/dev/backlight/backlight0";
|
||||
@@ -26,22 +26,25 @@ 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;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, 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);
|
||||
@@ -89,20 +90,31 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
#include "common/library.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <ddcutil_macros.h>
|
||||
#include <ddcutil_c_api.h>
|
||||
|
||||
static const char* detectWithDdcci(FFlist* result)
|
||||
// Try to be compatible with ddcutil 2.0
|
||||
#if DDCUTIL_VMAJOR >= 2
|
||||
double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
|
||||
#endif
|
||||
|
||||
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(libddcutil, &instance.config.library.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display)
|
||||
|
||||
__typeof__(&ddca_set_default_sleep_multiplier) ffddca_set_default_sleep_multiplier = dlsym(libddcutil, "ddca_set_default_sleep_multiplier");
|
||||
if (ffddca_set_default_sleep_multiplier)
|
||||
ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
|
||||
|
||||
libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330
|
||||
|
||||
FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL;
|
||||
if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0))
|
||||
if (ffddca_get_display_info_list2(false, &infoList) < 0)
|
||||
return "ddca_get_display_info_list2(false, &infoList) failed";
|
||||
|
||||
if (infoList->ct == 0)
|
||||
@@ -123,7 +135,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);
|
||||
@@ -134,14 +148,14 @@ static const char* detectWithDdcci(FFlist* result)
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
detectWithBacklight(result);
|
||||
|
||||
#ifdef FF_HAVE_DDCUTIL
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
if (result->length < displayServer->displays.length)
|
||||
detectWithDdcci(result);
|
||||
detectWithDdcci(options, result);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "brightness.h"
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +73,7 @@ static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer)
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectBrightness(FFlist* result)
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ typedef struct FFChassisResult
|
||||
FFstrbuf version;
|
||||
} FFChassisResult;
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result);
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options);
|
||||
const char* ffChassisTypeToString(uint32_t type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "common/settings.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
// Unlike other platforms, `smbios.chassis.type` return display string directly on my machine
|
||||
ffSettingsGetFreeBSDKenv("smbios.chassis.type", &result->type);
|
||||
|
||||
@@ -17,7 +17,7 @@ static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstr
|
||||
ffStrbufClear(buffer);
|
||||
}
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type);
|
||||
getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "chassis.h"
|
||||
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result)
|
||||
const char* ffDetectChassis(FF_MAYBE_UNUSED FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
{
|
||||
auto [arr, len] = vtProp.get<std::pair<const int32_t*, uint32_t>>();
|
||||
if(len == 0)
|
||||
return "ChassisTypes contain no data failed";
|
||||
return "ChassisTypes contain no data";
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
@@ -65,9 +65,9 @@ FF_MAYBE_UNUSED static const char* detectWithWmi(FFChassisResult* result)
|
||||
}
|
||||
|
||||
extern "C"
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
const char* ffDetectChassis(FFChassisResult* result, FFChassisOptions* options)
|
||||
{
|
||||
if (instance.config.allowSlowOperations)
|
||||
if (options->useWmi)
|
||||
return detectWithWmi(result);
|
||||
return detectWithRegistry(result);
|
||||
}
|
||||
|
||||
@@ -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,81 @@ 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
|
||||
|
||||
io_iterator_t iterator;
|
||||
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &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 +108,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;
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
ffDetectThermalTemp(&cpu->temperature);
|
||||
{
|
||||
if (!ffDetectCpuTemp(&cpu->temperature))
|
||||
ffDetectThermalTemp(&cpu->temperature);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -46,7 +47,8 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
ffParsePropLine(line, "isa :", cpuIsa) ||
|
||||
ffParsePropLine(line, "uarch :", cpuUarch) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) //For MIPS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,6 +116,10 @@ static void parseIsa(FFstrbuf* cpuIsa)
|
||||
}
|
||||
// The final ISA output of the above example is "rv64gch".
|
||||
}
|
||||
if(ffStrbufStartsWithS(cpuIsa, "mips"))
|
||||
{
|
||||
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
@@ -128,7 +134,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 +169,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";
|
||||
|
||||
|
||||
@@ -4,42 +4,58 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// We need to use uint64_t because sizeof(long) == 4 on Windows
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
|
||||
|
||||
static uint64_t inUseAll1, totalAll1;
|
||||
static FFlist cpuTimes1;
|
||||
|
||||
void ffPrepareCPUUsage(void)
|
||||
{
|
||||
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
assert(cpuTimes1.elementSize == 0);
|
||||
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
|
||||
ffGetCpuUsageInfo(&cpuTimes1);
|
||||
}
|
||||
|
||||
const char* ffGetCpuUsageResult(double* result)
|
||||
const char* ffGetCpuUsageResult(FFlist* result)
|
||||
{
|
||||
const char* error = NULL;
|
||||
if(inUseAll1 == 0 && totalAll1 == 0)
|
||||
if(cpuTimes1.elementSize == 0)
|
||||
{
|
||||
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
|
||||
if(error)
|
||||
return error;
|
||||
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
|
||||
error = ffGetCpuUsageInfo(&cpuTimes1);
|
||||
if(error) return error;
|
||||
ffTimeSleep(200);
|
||||
}
|
||||
|
||||
while(true)
|
||||
{
|
||||
uint64_t inUseAll2, totalAll2;
|
||||
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
|
||||
if(error)
|
||||
return error;
|
||||
if(cpuTimes1.length == 0) return "No CPU cores found";
|
||||
|
||||
if(inUseAll2 != inUseAll1)
|
||||
FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo));
|
||||
uint32_t retryCount = 0;
|
||||
|
||||
retry:
|
||||
error = ffGetCpuUsageInfo(&cpuTimes2);
|
||||
if(error) return error;
|
||||
if(cpuTimes1.length != cpuTimes2.length) return "Unexpected CPU usage result";
|
||||
|
||||
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
|
||||
{
|
||||
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
|
||||
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
|
||||
if (cpuTime2->totalAll <= cpuTime1->totalAll)
|
||||
{
|
||||
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
|
||||
inUseAll1 = inUseAll2;
|
||||
totalAll1 = totalAll2;
|
||||
return NULL;
|
||||
if (++retryCount <= 3)
|
||||
{
|
||||
ffListClear(&cpuTimes2);
|
||||
ffTimeSleep(200);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else
|
||||
ffTimeSleep(200);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
|
||||
{
|
||||
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
|
||||
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
|
||||
*(double*) ffListAdd(result) = (double)(cpuTime2->inUseAll - cpuTime1->inUseAll) / (double)(cpuTime2->totalAll - cpuTime1->totalAll) * 100;
|
||||
cpuTime1->inUseAll = cpuTime2->inUseAll;
|
||||
cpuTime1->totalAll = cpuTime2->totalAll;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
#ifndef FF_INCLUDED_detection_cpuusage_cpuusage
|
||||
#define FF_INCLUDED_detection_cpuusage_cpuusage
|
||||
|
||||
const char* ffGetCpuUsageResult(double* result);
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFCpuUsageInfo {
|
||||
uint64_t inUseAll;
|
||||
uint64_t totalAll;
|
||||
} FFCpuUsageInfo;
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes);
|
||||
|
||||
const char* ffGetCpuUsageResult(FFlist* result); // list of double
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,20 +4,29 @@
|
||||
#include <mach/processor_info.h>
|
||||
#include <mach/mach_host.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
host_cpu_load_info_data_t cpustats;
|
||||
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
natural_t numCPUs = 0U;
|
||||
processor_info_array_t cpuInfo;
|
||||
mach_msg_type_number_t numCpuInfo;
|
||||
|
||||
*inUseAll = *totalAll = 0;
|
||||
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
|
||||
return "host_processor_info() failed";
|
||||
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
|
||||
return "Unexpected host_processor_info() result";
|
||||
|
||||
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS)
|
||||
return "host_statistics() failed";
|
||||
|
||||
*inUseAll = cpustats.cpu_ticks[CPU_STATE_USER]
|
||||
+ cpustats.cpu_ticks[CPU_STATE_SYSTEM]
|
||||
+ cpustats.cpu_ticks[CPU_STATE_NICE];
|
||||
*totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE];
|
||||
for (natural_t i = 0U; i < numCPUs; ++i)
|
||||
{
|
||||
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
|
||||
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
|
||||
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
.inUseAll = (uint64_t)inUse,
|
||||
.totalAll = (uint64_t)total,
|
||||
};
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,36 @@
|
||||
#include "detection/cpuusage/cpuusage.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
// interrupt processing, user processes, system processing, lock spinning, and idling
|
||||
uint64_t cpTime[5];
|
||||
size_t neededLength = sizeof(cpTime);
|
||||
if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0)
|
||||
return "sysctlbyname(kern.cp_time) failed";
|
||||
size_t neededLength = 0;
|
||||
if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0)
|
||||
return "sysctlbyname(kern.cp_times, NULL) failed";
|
||||
|
||||
*inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3];
|
||||
*totalAll = *inUseAll + cpTime[4];
|
||||
uint32_t coreCount = (uint32_t) (neededLength / (CPUSTATES * sizeof(uint64_t)));
|
||||
assert(coreCount > 0);
|
||||
|
||||
FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength);
|
||||
if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0)
|
||||
return "sysctlbyname(kern.cp_times, cpTime) failed";
|
||||
|
||||
for (uint32_t i = 0; i < coreCount; ++i)
|
||||
{
|
||||
uint64_t* cpTime = cpTimes[i];
|
||||
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS];
|
||||
uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE];
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
.inUseAll = (uint64_t)inUse,
|
||||
.totalAll = (uint64_t)total,
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/cpuusage/cpuusage.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
|
||||
|
||||
FILE* procStat = fopen("/proc/stat", "r");
|
||||
FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r");
|
||||
if(procStat == NULL)
|
||||
{
|
||||
#ifdef __ANDROID__
|
||||
@@ -17,16 +16,22 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
return "fopen(\"""/proc/stat\", \"r\") == NULL";
|
||||
#endif
|
||||
}
|
||||
// Skip first line
|
||||
if (fscanf(procStat, "cpu%*[^\n]\n") < 0)
|
||||
return "fscanf() first line failed";
|
||||
|
||||
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
|
||||
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
|
||||
while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7)
|
||||
{
|
||||
fclose(procStat);
|
||||
return "fscanf() failed";
|
||||
}
|
||||
*inUseAll = user + nice + system;
|
||||
*totalAll = *inUseAll + idle + iowait + irq + softirq;
|
||||
uint64_t inUse = user + nice + system;
|
||||
uint64_t total = inUse + idle + iowait + irq + softirq;
|
||||
|
||||
fclose(procStat);
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
.inUseAll = (uint64_t)inUse,
|
||||
.totalAll = (uint64_t)total,
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
|
||||
@@ -16,8 +16,6 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size)))
|
||||
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed";
|
||||
|
||||
*inUseAll = *totalAll = 0;
|
||||
|
||||
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i)
|
||||
{
|
||||
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
|
||||
@@ -28,9 +26,14 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
|
||||
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
|
||||
coreInfo->KernelTime.QuadPart += dpcTime + interruptTime;
|
||||
|
||||
LONGLONG inUse = coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart;
|
||||
*inUseAll += (uint64_t)inUse;
|
||||
*totalAll += (uint64_t)(inUse + coreInfo->IdleTime.QuadPart);
|
||||
uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart);
|
||||
uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart;
|
||||
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
*info = (FFCpuUsageInfo) {
|
||||
.inUseAll = (uint64_t)inUse,
|
||||
.totalAll = (uint64_t)total,
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options);
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "de.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues("/usr/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("wayland-sessions/plasmawayland5.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
"plasmashell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // plasmashell 5.27.5
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getGnome(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gnome-shell/org.gnome.Extensions", "version :", result);
|
||||
|
||||
if (result->length == 0)
|
||||
{
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
"gnome-shell",
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL) // GNOME Shell 44.1
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getCinnamon(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", result);
|
||||
}
|
||||
|
||||
static void getMate(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY major = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY minor = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY micro = ffStrbufCreate();
|
||||
|
||||
ffParsePropFileDataValues("mate-about/mate-version.xml", 3, (FFpropquery[]) {
|
||||
{"<platform>", &major},
|
||||
{"<minor>", &minor},
|
||||
{"<micro>", µ}
|
||||
});
|
||||
|
||||
ffParseSemver(result, &major, &minor, µ);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"mate-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrAfterFirstC(result, ' ');
|
||||
ffStrbufTrim(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getXFCE4(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", result);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if(result->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, &entry->d_name[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"xfce4-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(result, '(');
|
||||
ffStrbufSubstrAfterFirstC(result, ' ');
|
||||
ffStrbufTrim(result, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getLXQt(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("gconfig/lxqt.pc", "Version:", result);
|
||||
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", result);
|
||||
|
||||
if(result->length == 0 && options->slowVersionDetection)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(result, (char* const[]){
|
||||
"lxqt-session",
|
||||
"-v",
|
||||
NULL
|
||||
});
|
||||
|
||||
result->length = 0; //don't set '\0' byte
|
||||
ffParsePropLines(result->chars , "liblxqt", result);
|
||||
}
|
||||
}
|
||||
|
||||
static void getBudgie(FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileData("budgie/budgie-version.xml", "<str>", result);
|
||||
}
|
||||
|
||||
const char* ffDetectDEVersion(const FFstrbuf* deName, FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
if (ffStrbufEqualS(deName, FF_DE_PRETTY_PLASMA))
|
||||
getKDE(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME) || ffStrbufEqualS(deName, FF_DE_PRETTY_GNOME))
|
||||
getGnome(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_CINNAMON))
|
||||
getCinnamon(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_XFCE4))
|
||||
getXFCE4(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_MATE))
|
||||
getMate(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_LXQT))
|
||||
getLXQt(result, options);
|
||||
else if (ffStrbufEqualS(deName, FF_DE_PRETTY_BUDGIE))
|
||||
getBudgie(result, options);
|
||||
else
|
||||
return "Unsupported DE";
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "de.h"
|
||||
|
||||
const char* ffDetectDEVersion(FF_MAYBE_UNUSED const FFstrbuf* deName, FF_MAYBE_UNUSED FFstrbuf* result, FF_MAYBE_UNUSED FFDEOptions* options)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
|
||||
typedef struct FFDisk
|
||||
{
|
||||
FFstrbuf mountFrom;
|
||||
FFstrbuf mountpoint;
|
||||
FFstrbuf filesystem;
|
||||
FFstrbuf name;
|
||||
FFDiskType type;
|
||||
FFDiskVolumeType type;
|
||||
|
||||
uint64_t bytesUsed;
|
||||
uint64_t bytesFree;
|
||||
uint64_t bytesAvailable;
|
||||
uint64_t bytesTotal;
|
||||
|
||||
uint32_t filesUsed;
|
||||
@@ -23,6 +26,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,70 @@
|
||||
#include "disk.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
{
|
||||
if(ffStrbufEqualS(&disk->filesystem, "zfs"))
|
||||
{
|
||||
disk->type = !ffStrStartsWith(fs->f_mntfromname, "zroot/") || ffStrStartsWith(fs->f_mntfromname, "zroot/ROOT/")
|
||||
? FF_DISK_TYPE_REGULAR_BIT
|
||||
: FF_DISK_TYPE_SUBVOLUME_BIT;
|
||||
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(!ffStrStartsWith(fs->f_mntfromname, "/dev/"))
|
||||
disk->type = FF_DISK_TYPE_HIDDEN_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_TYPE_EXTERNAL_BIT;
|
||||
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 "util/apple/cf_helpers.h"
|
||||
|
||||
#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 +72,25 @@ const char* ffDetectDisksImpl(FFlist* disks)
|
||||
if(fs->f_ffree < 0) fs->f_ffree = 0;
|
||||
#endif
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
|
||||
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;
|
||||
|
||||
+132
-104
@@ -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,18 +96,24 @@ 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();
|
||||
|
||||
//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);
|
||||
@@ -133,6 +125,8 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
detectNameFromPath(disk, &deviceStat, &basePath);
|
||||
}
|
||||
|
||||
if (disk->name.length == 0) return;
|
||||
|
||||
// Basic\x20data\x20partition
|
||||
for (uint32_t i = ffStrbufFirstIndexS(&disk->name, "\\x");
|
||||
i != disk->name.length;
|
||||
@@ -152,52 +146,100 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
|
||||
|
||||
#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 isRemovable(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;
|
||||
|
||||
// /sys/block/sdx/removable
|
||||
ffStrbufAppendS(&basePath, entry->d_name);
|
||||
ffStrbufAppendS(&basePath, "/removable");
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void detectType(const FFlist* disks, FFDisk* currentDisk)
|
||||
{
|
||||
if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return;
|
||||
|
||||
if(isRemovable(currentDisk))
|
||||
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
|
||||
@@ -209,69 +251,55 @@ 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;
|
||||
|
||||
//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,31 @@ 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];
|
||||
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 +60,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 +74,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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user