mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
226 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b0c32a35f | |||
| db269d29e8 | |||
| f9f628eae6 | |||
| 92e9fbf2eb | |||
| db6e4f4bfc | |||
| b662db452f | |||
| 0d2ccb5fe5 | |||
| d33b5d60b6 | |||
| ef5d12395b | |||
| e18c261054 | |||
| 8851821484 | |||
| 3489cc8fe8 | |||
| 28bc97b92b | |||
| dbc5a7961e | |||
| 5f43f63990 | |||
| b775fe7486 | |||
| 60eaa326a2 | |||
| 672d4ad543 | |||
| 96e9e61437 | |||
| dbc6f70f19 | |||
| dfc9bc265c | |||
| 2ce511c4d3 | |||
| 99415a3841 | |||
| 244625d26a | |||
| 840434e709 | |||
| 72afa9ef99 | |||
| 7400f14322 | |||
| 85654316c7 | |||
| 8ecd58dd14 | |||
| 65c7f68c31 | |||
| bf6d0f871a | |||
| 3cd7c6c916 | |||
| 3227e934de | |||
| b66a009046 | |||
| 6ef4f62d5b | |||
| c038024108 | |||
| df49a01827 | |||
| 924c670915 | |||
| be89dff12a | |||
| c1807a1108 | |||
| b569acbb5d | |||
| 6e571a3163 | |||
| 01e78e2179 | |||
| 1b219a9d5c | |||
| 0ac01003b2 | |||
| a36bdfabd0 | |||
| 570abb194a | |||
| 4e00f37be9 | |||
| 334afc9838 | |||
| 64f9e53a36 | |||
| b94c6ab8d5 | |||
| 38ea333644 | |||
| efbdaf7aaf | |||
| aee7b37fc8 | |||
| 664460cd34 | |||
| a66e1b2e6d | |||
| 8000574a82 | |||
| 2eae5a86d2 | |||
| 75da934815 | |||
| ac71ebcad9 | |||
| 383a6c8a05 | |||
| 8e79fde0d9 | |||
| 4f4622eab9 | |||
| a2327b7350 | |||
| b76ada7f30 | |||
| 59b568a6d0 | |||
| 3d6bd26e59 | |||
| 4e17688b7c | |||
| f34548621f | |||
| 7a2e071081 | |||
| de7b57d807 | |||
| 6de9d0c024 | |||
| 8f69533f30 | |||
| d463853aeb | |||
| 1047d1cf6e | |||
| 0bfa12c38c | |||
| c8e4962cfd | |||
| 171005b6a3 | |||
| 8526f4a021 | |||
| 3e5d129248 | |||
| 6e98db3bf3 | |||
| ff0236639a | |||
| 959bf769fb | |||
| 3ae7c4f788 | |||
| 143b3df771 | |||
| c0c59a890a | |||
| 3c5f69b874 | |||
| 36a452c852 | |||
| c66b32fc6f | |||
| bc129a65d9 | |||
| 1137e8d1c9 | |||
| 95a44d3a33 | |||
| b8b2fab499 | |||
| 7aceb1072a | |||
| 13723893ba | |||
| 6fd4720faf | |||
| 966b8452b7 | |||
| 8dc4f77f42 | |||
| ab0240e9b7 | |||
| 399f262692 | |||
| d1385804bb | |||
| 948a965c7a | |||
| a13935e232 | |||
| 46f920ae2a | |||
| e79b561f2a | |||
| 9018fda92e | |||
| 76b8b9a44b | |||
| 36a129f668 | |||
| 24e94acbb9 | |||
| 716f0a3bbb | |||
| f839fcfa29 | |||
| 41d930b1e1 | |||
| 5e615d12d5 | |||
| 17711ee5c8 | |||
| 9ff3142b61 | |||
| 8e5c2adda3 | |||
| 01d37653b0 | |||
| f5dbbb70ef | |||
| fc3f47742a | |||
| 1d2b6c0b1a | |||
| 5ebf984e9a | |||
| bfa59d2c04 | |||
| c1c59cff6d | |||
| 519dae9462 | |||
| 34419d9bcf | |||
| 532b3cd457 | |||
| 437006f5f1 | |||
| 1c858ae835 | |||
| 349fdd47e4 | |||
| c64854804d | |||
| f3e54f33c2 | |||
| 5f3ff07b4b | |||
| e8db71fe19 | |||
| 8984aa740e | |||
| c081268b7c | |||
| fae8d1dd10 | |||
| 217ea61568 | |||
| ba7885913d | |||
| a8afd05d19 | |||
| f4f1592bfa | |||
| cdc8124883 | |||
| c53191a441 | |||
| 14aadd5b61 | |||
| e38f094c16 | |||
| 452d52c217 | |||
| c585e09ef0 | |||
| 464e00d616 | |||
| b8e25bdc4e | |||
| 379c39d8b5 | |||
| f2a41b82bc | |||
| d1a98fe69f | |||
| ef3412f81b | |||
| 1812c30fbf | |||
| 3c45f2e590 | |||
| 735a464f68 | |||
| 3e3dfb4a02 | |||
| f77a9c185d | |||
| d3a5f986a8 | |||
| ef60910e51 | |||
| 565934ba2e | |||
| 5c5e12f0a7 | |||
| b3e7451a08 | |||
| da76dcb2fe | |||
| cbc8b1f11d | |||
| 5ca4268be2 | |||
| ff8bfadd25 | |||
| 1fc0f75776 | |||
| bf707c2e94 | |||
| 08cd4ac1ee | |||
| 48fc598ccb | |||
| 3a8138e3da | |||
| 4251456619 | |||
| 5bc6d16138 | |||
| 11374e73ae | |||
| 373cb4106a | |||
| a0949c5675 | |||
| 97b1eb155f | |||
| 093cc6fba2 | |||
| c8a3ae9186 | |||
| 778013aec9 | |||
| e6af1bfb91 | |||
| 9d8a83349c | |||
| 3bc6be9139 | |||
| 1eef6f837b | |||
| 85ed4b136f | |||
| 339e08fef1 | |||
| 5957831f3f | |||
| 016b1e6961 | |||
| 486ade0e71 | |||
| e021cfe77a | |||
| a016397961 | |||
| 99e8d1f2bb | |||
| 263d2902dd | |||
| 292fa0686f | |||
| f2755a844b | |||
| 1d21d02878 | |||
| b3062499f4 | |||
| 49bb957c86 | |||
| 8f27e43929 | |||
| 8774fb3fb7 | |||
| 356501270a | |||
| 5a04a2ecc3 | |||
| edcd7995e5 | |||
| 7f212025de | |||
| 63cc8e5523 | |||
| c3023259e2 | |||
| 994a8b4dd0 | |||
| 76710c8159 | |||
| 70820e424b | |||
| 9221e2b41d | |||
| 71a2e55869 | |||
| dc5ff01e74 | |||
| fc8ddce182 | |||
| dd67010e5c | |||
| d1ba690973 | |||
| 01f400c15f | |||
| 33c905aa99 | |||
| fe7c4f724e | |||
| abadcb95bd | |||
| 3d8050fd5c | |||
| 4d842ac6b6 | |||
| b76e62685e | |||
| 1279bbcf28 | |||
| 4e9fecc767 | |||
| 1c4953a467 | |||
| 3ad5d5c8b0 |
+130
-77
@@ -35,7 +35,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
@@ -73,8 +73,14 @@ jobs:
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev python3-requests
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
@@ -87,7 +93,7 @@ jobs:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -111,7 +117,7 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
@@ -125,7 +131,7 @@ jobs:
|
||||
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-22.04-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -133,24 +139,45 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: aarch64
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -158,9 +185,9 @@ jobs:
|
||||
name: fastfetch-linux-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7:
|
||||
name: Linux-armv7
|
||||
runs-on: ubuntu-22.04
|
||||
linux-armv7l:
|
||||
name: Linux-armv7l
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -169,7 +196,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv7
|
||||
@@ -181,7 +208,7 @@ jobs:
|
||||
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
|
||||
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
|
||||
dpkg -i *.deb
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -189,17 +216,17 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv7
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv6:
|
||||
name: Linux-armv6
|
||||
runs-on: ubuntu-22.04
|
||||
linux-armv6l:
|
||||
name: Linux-armv6l
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -208,7 +235,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv6
|
||||
@@ -217,7 +244,7 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -225,17 +252,17 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv6
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -244,7 +271,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
@@ -252,7 +279,7 @@ jobs:
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -260,7 +287,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -270,7 +297,7 @@ jobs:
|
||||
|
||||
linux-ppc64le:
|
||||
name: Linux-ppc64le
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -279,7 +306,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ppc64le
|
||||
@@ -287,7 +314,7 @@ jobs:
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -295,7 +322,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -303,6 +330,41 @@ jobs:
|
||||
name: fastfetch-linux-ppc64le
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-s390x:
|
||||
name: Linux-s390x
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: s390x
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-s390x
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
@@ -311,19 +373,17 @@ jobs:
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
with:
|
||||
branch: v3.19
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev py3-requests gcc g++
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -GNinja .
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
@@ -334,7 +394,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -360,20 +420,12 @@ jobs:
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
@@ -390,7 +442,7 @@ jobs:
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -422,7 +474,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
cpack
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -452,15 +504,15 @@ jobs:
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py311-requests chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On .
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -485,17 +537,17 @@ jobs:
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py39-requests chafa libelf
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On .
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -523,15 +575,15 @@ jobs:
|
||||
version: '7.6'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -556,18 +608,18 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.0'
|
||||
version: '10.1'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick pulseaudio opencl-headers ocl-icd py312-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick opencl-headers ocl-icd
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -626,7 +678,7 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
@@ -647,10 +699,11 @@ jobs:
|
||||
needs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-armv7
|
||||
- linux-armv6
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- linux-s390x
|
||||
- musl-amd64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
|
||||
+123
@@ -1,3 +1,126 @@
|
||||
# 2.39.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix a regression that PublicIP detection fails randomly (PublicIP, #1629)
|
||||
|
||||
# 2.39.0
|
||||
|
||||
Changes:
|
||||
* OSMesa backend for OpenGL detection is removed (#1618)
|
||||
* Fastfetch no longer tries to use the private framework `Apple80211` to acquire SSID for Wifi module, which is only useful for macOS Sonoma (Wifi, macOS)
|
||||
|
||||
Features:
|
||||
* Improve accuracy of HDR support on Windows 11 24H2 (Display, Windows)
|
||||
* Improve performance of SSID detection on macOS Sequoia (Wifi, macOS, #1597)
|
||||
* Support warp terminal version detection on Windows (Terminal, Windows)
|
||||
* Support default route detection on OpenBSD & DragonFly BSD (LocalIP, OpenBSD / DragonFly)
|
||||
* Improve bash completion script
|
||||
* Improve performance of networking (PublicIP / Weather)
|
||||
* Support pkgsrc package manager detection on Linux (Packages, Linux)
|
||||
|
||||
Logo:
|
||||
* Add Common Torizon OS
|
||||
* Change FoxOS to WolfOS
|
||||
* Add Bredos
|
||||
* Add NetBSD2
|
||||
|
||||
# 2.38.0
|
||||
|
||||
Bugfixes:
|
||||
* Fix empty battery slots handling (Battery, Haiku, #1575)
|
||||
* Fix `{day-pretty}` output in custom format (DateTime, Windows)
|
||||
* Fix VanillaOS detection (OS, Linux)
|
||||
* Fix secure boot testing (Bootmgr, Linux, #1584)
|
||||
* Fix the SI unit "kB" in help message (#1589)
|
||||
* Fix segfault on macOS 10.15 when using the binary downloaded from Github Releases (Camera, macOS, #1594)
|
||||
|
||||
Features:
|
||||
* Support Chassis module in macOS (Chassis, macOS)
|
||||
* Allow customize key format with kernel name and distro name (OS)
|
||||
* Add missing `{icon}` in custom key format (Battery)
|
||||
* Add missing `{mountpoint}` and `{mount-from}` in custom output format (Disk, #1577)
|
||||
* Support percentage num & bar in custom format (GPU, #1583)
|
||||
* Support `pisi` package manager detection (Packages, Linux)
|
||||
* Support termite terminal font detection (TerminalFont, Linux)
|
||||
* Report monitor type in Brightness module (Brightness)
|
||||
|
||||
Logo:
|
||||
* Add `opensuse-tumbleweed_small`
|
||||
* Add `Bedrock_small`
|
||||
* Add `fastfetch`
|
||||
* Remove some unnecessary distro names
|
||||
|
||||
# 2.37.0
|
||||
|
||||
Changes:
|
||||
* Option `--escape-bedrock` is removed. The function is always enabled now.
|
||||
|
||||
Features:
|
||||
* Support for Haiku is greatly improved (Haiku)
|
||||
* CPU, GPU, Disk, Sound, Terminal, Terminal Font, Init System, Battery, Mouse, Keyboard, NetIO, CPU Usage, Physical Disk and OpenGL should work on Haiku now
|
||||
* SMBIOS related modules (Host, Bios, Board, Chassis, Physical Memory) should work in platforms with legacy BIOS system.
|
||||
* Support for Gamepad and Bluetooth are WIP.
|
||||
* Some bugs are found and fixed.
|
||||
* Remove `python-requests` dependency in `scripts/gen-*.py`.
|
||||
* Add cmake option `-DENABLE_EMBEDDED_AMDGPUIDS=BOOL` (disabled by default)
|
||||
* If enabled, fastfetch will embed the newest [`amdgpu.ids`](https://gitlab.freedesktop.org/mesa/drm/-/blob/main/data/amdgpu.ids?ref_type=heads) file into fastfetch binary.
|
||||
* Weather module now honors `display.temp.unit` option (#1560, Weather)
|
||||
* Support Physical Memory module in NetBSD (PhysicalMemory, NetBSD)
|
||||
* Requires root permission
|
||||
* Improve non-intel CPU detection in NetBSD (#1573, CPU, NetBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fix building in macOS 10.13 (GPU, macOS)
|
||||
* Properly round percent values when detecting volume (#1558, Sound)
|
||||
* Fix Physical Memory module doesn't work in `--format json` mode
|
||||
* Add some missing variable inits (GPU, Linux)
|
||||
* Fix `--localip-default-route-only false` not working with `--gen-config` (#1570, LocalIP)
|
||||
|
||||
Logo:
|
||||
* Update Rosa linux
|
||||
* Add Haiku2
|
||||
|
||||
# 2.36.1
|
||||
|
||||
Changes:
|
||||
* To use [the native arm64 runner of Github Action](https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/), Linux aarch64 binary is built with Ubuntu 22.04 (Glibc 2.35, Debian 12).
|
||||
|
||||
Bugfixes:
|
||||
* Chimera Linux logo is now displayed correctly (#1554, Logo)
|
||||
* Regression of 2.36.0
|
||||
* Fix building on Haiku
|
||||
|
||||
Logo:
|
||||
* Fix ALT Linux
|
||||
|
||||
# 2.36.0
|
||||
|
||||
Bugfixes:
|
||||
* Trim leading slash for login shells (Shell, OpenBSD)
|
||||
* Prefer SOC name if available over CPU name (CPU, Linux)
|
||||
|
||||
Features:
|
||||
* Use kernel API to detect sound devices (Sound, NetBSD)
|
||||
* Use sndio for sound server detection on OpenBSD (Sound, OpenBSD)
|
||||
* Add minimal implementation for Haiku (#1538, Haiku)
|
||||
* Support CPU & GPU temperature detection for M4x (CPU / GPU, macOS)
|
||||
* Support VMEM size detection for old Nvidia cards (GPU, Linux)
|
||||
* Use [recommendedMaxWorkingSetSize](https://developer.apple.com/documentation/metal/mtldevice/recommendedmaxworkingsetsize) as total GPU mem size (GPU, macOS)
|
||||
* Support Physical core count and CPU package count detection for loongarch (CPU, Linux)
|
||||
* Split ID_LIKE when used for distro matching (#1540, Logo)
|
||||
* Capitalize `{type}`'s first letter in custom format (#1543, Display)
|
||||
* Support model name detection for s390x (CPU, Linux)
|
||||
* Support more Armbian variants detection (#1547, OS, Linux)
|
||||
* Support the syntax of `{$ENV_VAR}` in custom format, which will be replaced by the value of the environment variable `ENV_VAR` (#1541)
|
||||
* This is another way to pass 3rd-party data to fastfetch besides `Custom` module.
|
||||
* Improve performance of Tilix version detection (Terminal, Linux)
|
||||
|
||||
Logo:
|
||||
* Update arch_old
|
||||
* Add Nexa Linux
|
||||
* Add filotimo
|
||||
* Update some distro names
|
||||
|
||||
# 2.35.0
|
||||
|
||||
Bugfixes:
|
||||
|
||||
+148
-30
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.35.0
|
||||
VERSION 2.39.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -30,6 +30,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
|
||||
set(DragonFly TRUE CACHE BOOL "..." FORCE)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
|
||||
set(SunOS TRUE CACHE BOOL "..." FORCE)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku")
|
||||
set(Haiku TRUE CACHE BOOL "..." FORCE)
|
||||
elseif(NOT APPLE AND NOT WIN32)
|
||||
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
@@ -54,7 +56,7 @@ include(CheckIncludeFile)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
@@ -62,23 +64,22 @@ cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBS
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" 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_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD OR SunOS" OFF)
|
||||
@@ -92,6 +93,7 @@ option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by gith
|
||||
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
|
||||
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
|
||||
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
|
||||
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
|
||||
|
||||
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
|
||||
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
|
||||
@@ -100,7 +102,7 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
|
||||
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
|
||||
endif()
|
||||
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PKG PKGTOOL RPM SCOOP SNAP SORCERY WINGET XBPS)
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SORCERY WINGET XBPS)
|
||||
foreach(package_manager ${PACKAGE_MANAGERS})
|
||||
if(package_manager STREQUAL "WINGET")
|
||||
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
|
||||
@@ -139,7 +141,7 @@ set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=retu
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")
|
||||
|
||||
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
|
||||
if(WIN32 OR Haiku OR ENABLE_DIRECTX_HEADERS)
|
||||
enable_language(CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
|
||||
@@ -269,11 +271,16 @@ endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
|
||||
if(Python_FOUND)
|
||||
if(NOT EXISTS "${PROJECT_BINARY_DIR}/pci.ids")
|
||||
message(STATUS "'${PROJECT_BINARY_DIR}/pci.ids' is missing, downloading...")
|
||||
file(DOWNLOAD "https://pci-ids.ucw.cz/v2.2/pci.ids" "${PROJECT_BINARY_DIR}/pci.ids")
|
||||
endif()
|
||||
message(STATUS "Generating 'fastfetch_pciids.c.inc'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py"
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" "${PROJECT_BINARY_DIR}/pci.ids"
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc"
|
||||
RESULT_VARIABLE PYTHON_PCIIDS_RETCODE)
|
||||
if(NOT PYTHON_PCIIDS_RETCODE EQUAL 0)
|
||||
file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
|
||||
message(FATAL_ERROR "Failed to generate 'fastfetch_pciids.c.inc'")
|
||||
endif()
|
||||
else()
|
||||
@@ -282,6 +289,26 @@ if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
|
||||
if(Python_FOUND)
|
||||
if(NOT EXISTS "${PROJECT_BINARY_DIR}/amdgpu.ids")
|
||||
message(STATUS "'${PROJECT_BINARY_DIR}/amdgpu.ids' is missing, downloading...")
|
||||
file(DOWNLOAD "https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids" "${PROJECT_BINARY_DIR}/amdgpu.ids")
|
||||
endif()
|
||||
message(STATUS "Generating 'fastfetch_amdgpuids.c.inc'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-amdgpuids.py" "${PROJECT_BINARY_DIR}/amdgpu.ids"
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc"
|
||||
RESULT_VARIABLE PYTHON_AMDGPUIDS_RETCODE)
|
||||
if(NOT PYTHON_AMDGPUIDS_RETCODE EQUAL 0)
|
||||
file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
|
||||
message(FATAL_ERROR "Failed to generate 'fastfetch_amdgpuids.c.inc'")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Python3 is not found, 'fastfetch_amdgpuids.c.inc' will not be generated")
|
||||
set(ENABLE_EMBEDDED_AMDGPUIDS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(Python_FOUND)
|
||||
message(STATUS "Generating 'fastfetch.1'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py"
|
||||
@@ -337,6 +364,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/library.c
|
||||
src/common/modules.c
|
||||
src/common/netif/netif.c
|
||||
src/common/networking/networking_common.c
|
||||
src/common/option.c
|
||||
src/common/parsing.c
|
||||
src/common/printing.c
|
||||
@@ -465,7 +493,7 @@ if(LINUX)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
@@ -546,7 +574,7 @@ 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/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_android.c
|
||||
src/detection/bios/bios_android.c
|
||||
@@ -612,7 +640,7 @@ elseif(FreeBSD)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_bsd.c
|
||||
@@ -703,7 +731,7 @@ elseif(NetBSD)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_nbsd.c
|
||||
@@ -716,13 +744,13 @@ elseif(NetBSD)
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_nbsd.c
|
||||
src/detection/cpu/cpu_nbsd.c
|
||||
src/detection/cpucache/cpucache_nosupport.c
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_nbsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
@@ -761,7 +789,7 @@ elseif(NetBSD)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_nbsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_nbsd.c
|
||||
src/detection/swap/swap_obsd.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -785,7 +813,7 @@ elseif(OpenBSD)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_obsd.c
|
||||
@@ -843,7 +871,7 @@ elseif(OpenBSD)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_obsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_obsd.c
|
||||
src/detection/swap/swap_obsd.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -866,7 +894,7 @@ 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/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_apple.c
|
||||
@@ -877,7 +905,7 @@ elseif(APPLE)
|
||||
src/detection/bootmgr/bootmgr_apple.c
|
||||
src/detection/brightness/brightness_apple.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/chassis/chassis_apple.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/cpucache/cpucache_apple.c
|
||||
src/detection/cpuusage/cpuusage_apple.c
|
||||
@@ -937,7 +965,7 @@ 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/networking/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
@@ -1006,13 +1034,14 @@ elseif(WIN32)
|
||||
src/util/windows/version.c
|
||||
src/util/platform/FFPlatform_windows.c
|
||||
src/util/binary_windows.c
|
||||
src/util/debug_windows.c
|
||||
)
|
||||
elseif(SunOS)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_windows.c
|
||||
@@ -1088,6 +1117,76 @@ elseif(SunOS)
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(Haiku)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_haiku.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_haiku.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_haiku.c
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_haiku.c
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_haiku.cpp
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/disk/disk_haiku.cpp
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_haiku.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_nosupport.c
|
||||
src/detection/displayserver/displayserver_haiku.cpp
|
||||
src/detection/font/font_haiku.cpp
|
||||
src/detection/gpu/gpu_haiku.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/initsystem/initsystem_haiku.c
|
||||
src/detection/keyboard/keyboard_haiku.cpp
|
||||
src/detection/libc/libc_nosupport.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/loadavg/loadavg_nosupport.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_haiku.cpp
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_haiku.c
|
||||
src/detection/mouse/mouse_haiku.cpp
|
||||
src/detection/netio/netio_haiku.cpp
|
||||
src/detection/opengl/opengl_haiku.cpp
|
||||
src/detection/os/os_haiku.c
|
||||
src/detection/packages/packages_haiku.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_haiku.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_haiku.cpp
|
||||
src/detection/swap/swap_haiku.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalsize/terminalsize_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/tpm/tpm_nosupport.c
|
||||
src/detection/uptime/uptime_haiku.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/haiku/version.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DIRECTX_HEADERS)
|
||||
@@ -1112,6 +1211,9 @@ endif()
|
||||
if(LINUX)
|
||||
check_function_exists(statx HAVE_STATX)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SYSTEM_YYJSON)
|
||||
find_package(yyjson)
|
||||
@@ -1206,6 +1308,8 @@ elseif(NetBSD)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-char-subscripts")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R7/lib -Wl,-rpath,/usr/pkg/lib") # ditto
|
||||
elseif(Haiku)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
endif()
|
||||
|
||||
if(FreeBSD OR OpenBSD OR NetBSD)
|
||||
@@ -1226,6 +1330,10 @@ if(HAVE_WCWIDTH)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH)
|
||||
endif()
|
||||
|
||||
if(HAVE_PIPE2)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PIPE2)
|
||||
endif()
|
||||
|
||||
if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
|
||||
@@ -1371,10 +1479,6 @@ else()
|
||||
"GL"
|
||||
)
|
||||
endif()
|
||||
ff_lib_enable(OSMESA
|
||||
"osmesa"
|
||||
"OSMesa"
|
||||
)
|
||||
ff_lib_enable(OPENCL
|
||||
"OpenCL"
|
||||
"OpenCL"
|
||||
@@ -1432,6 +1536,9 @@ endif()
|
||||
if(ENABLE_EMBEDDED_PCIIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1)
|
||||
endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1465,7 +1572,6 @@ elseif(APPLE)
|
||||
PRIVATE "-F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework DisplayServices"
|
||||
PRIVATE "-weak_framework MediaRemote"
|
||||
PRIVATE "-weak_framework Apple80211"
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1504,6 +1610,7 @@ elseif(OpenBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "kvm"
|
||||
PRIVATE "sndio"
|
||||
)
|
||||
elseif(NetBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1533,6 +1640,17 @@ elseif(ANDROID)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
elseif(Haiku)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "network"
|
||||
PRIVATE "bnetapi"
|
||||
PRIVATE "media"
|
||||
PRIVATE "device"
|
||||
PRIVATE "bluetooth"
|
||||
PRIVATE "GL"
|
||||
PRIVATE "be"
|
||||
PRIVATE "gnu"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2023 Linus Dierheimer
|
||||
Copyright (c) 2022-2024 Carter Li
|
||||
Copyright (c) 2022-2025 Carter Li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
[](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 it prettily. It is written mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, macOS, SunOS and Windows 7+ are supported.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it prettily. It is written mainly in C, with performance and customizability in mind. Currently, Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku and SunOS are supported.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -29,6 +29,10 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
|
||||
Some distros package an outdated fastfetch version. Older versions receive no support, so please try always to use the latest version.
|
||||
|
||||
<a href="https://repology.org/project/fastfetch/versions">
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
@@ -47,8 +51,6 @@ Some distros package an outdated fastfetch version. Older versions receive no su
|
||||
|
||||
You may need `sudo`, `doas` or `sup` to run these commands.
|
||||
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging).
|
||||
|
||||
If fastfetch is not packaged for your distro or an outdated version is packaged, [linuxbrew](https://brew.sh/) is a good alternative: `brew install fastfetch`
|
||||
|
||||
### macOS
|
||||
@@ -73,6 +75,10 @@ You may also download the program directly from [the GitHub releases page](https
|
||||
|
||||
* `pkg install fastfetch`
|
||||
|
||||
### Nightly
|
||||
|
||||
<https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview>
|
||||
|
||||
## Build from source
|
||||
|
||||
See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
@@ -91,18 +97,6 @@ Fastfetch uses the JSONC (or JSON with comments) for configuration. [See Wiki fo
|
||||
|
||||
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
|
||||
## Packaging
|
||||
|
||||
### Repositories
|
||||
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
|
||||
### Manual
|
||||
|
||||
* DEB / RPM package: `cmake --build . --target package`
|
||||
* Install directly: `cmake --install . --prefix /usr/local`
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Neofetch is good enough. Why do I need fastfetch?
|
||||
|
||||
+119
-428
@@ -1,430 +1,121 @@
|
||||
__fastfetch_complete_help()
|
||||
{
|
||||
local __ff_helps=(
|
||||
"color"
|
||||
"format"
|
||||
"config"
|
||||
"os-format"
|
||||
"host-format"
|
||||
"kernel-format"
|
||||
"uptime-format"
|
||||
"processes-format"
|
||||
"packages-format"
|
||||
"shell-format"
|
||||
"display-format"
|
||||
"de-format"
|
||||
"wm-format"
|
||||
"wmtheme-format"
|
||||
"theme-format"
|
||||
"icons-format"
|
||||
"font-format"
|
||||
"cursor-format"
|
||||
"terminal-format"
|
||||
"terminalfont-format"
|
||||
"cpu-format"
|
||||
"cpuusage-format"
|
||||
"gpu-format"
|
||||
"memory-format"
|
||||
"swap-format"
|
||||
"disk-format"
|
||||
"battery-format"
|
||||
"poweradapter-format"
|
||||
"locale-format"
|
||||
"localip-format"
|
||||
"publicip-format"
|
||||
"player-format"
|
||||
"media-format"
|
||||
"datetime-format"
|
||||
"date-format"
|
||||
"time-format"
|
||||
"vulkan-format"
|
||||
"opengl-format"
|
||||
"opencl-format"
|
||||
"bluetooth-format"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_fastfetch() {
|
||||
# Use Bash built-in variables directly
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
# Check if Python is available
|
||||
if ! command -v python3 &>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Handle standard completion cases
|
||||
case "$prev" in
|
||||
--color|--color-keys|--color-title|--color-output|--color-separator|--*-color|--*-key-color|--*-output-color|--logo-color-[1-9]|--percent-color-*|--temp-color-*)
|
||||
local -a colors=("black" "red" "green" "yellow" "blue" "magenta" "cyan" "white" "default")
|
||||
COMPREPLY=($(compgen -W "${colors[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--logo|-l)
|
||||
local -a logos
|
||||
readarray -t logos < <(fastfetch --list-logos autocompletion 2>/dev/null)
|
||||
logos+=("none" "small")
|
||||
COMPREPLY=($(compgen -W "${logos[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--config|-c)
|
||||
local -a presets
|
||||
readarray -t presets < <(fastfetch --list-presets autocompletion 2>/dev/null)
|
||||
presets+=("none")
|
||||
COMPREPLY=($(compgen -W "${presets[*]}" -- "$cur"))
|
||||
# Also allow file path completion
|
||||
if type _filedir &>/dev/null; then
|
||||
_filedir
|
||||
elif type compgen &>/dev/null; then
|
||||
COMPREPLY+=($(compgen -f -- "$cur"))
|
||||
fi
|
||||
return
|
||||
;;
|
||||
--structure|-s)
|
||||
# Get all module names in lowercase only
|
||||
local -a structures
|
||||
readarray -t structures < <(fastfetch --list-modules autocompletion 2>/dev/null | cut -d':' -f1 | tr '[:upper:]' '[:lower:]')
|
||||
COMPREPLY=($(compgen -W "${structures[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--help|-h)
|
||||
local -a modules
|
||||
readarray -t modules < <(fastfetch --list-modules autocompletion 2>/dev/null)
|
||||
# Convert to lowercase and keep only module names
|
||||
local -a module_names=()
|
||||
for module in "${modules[@]}"; do
|
||||
module_names+=($(echo "$module" | cut -d':' -f1 | tr '[:upper:]' '[:lower:]')-format)
|
||||
done
|
||||
module_names+=("format" "color")
|
||||
COMPREPLY=($(compgen -W "${module_names[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--format)
|
||||
COMPREPLY=($(compgen -W "json default" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--*-format)
|
||||
# Format string completion, handle spaces
|
||||
return
|
||||
;;
|
||||
--*path*|--*file*|--gen-config*|--*data*)
|
||||
# File path completion
|
||||
if type _filedir &>/dev/null; then
|
||||
_filedir
|
||||
elif type compgen &>/dev/null; then
|
||||
COMPREPLY=($(compgen -f -- "$cur"))
|
||||
fi
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
# If not a special option, generate all possible options
|
||||
if [[ "$cur" == -* ]]; then
|
||||
local -a opts
|
||||
readarray -t opts < <(python3 - "$cur" <<'EOF'
|
||||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
def main(current):
|
||||
try:
|
||||
# Use fastfetch --help-raw to get option data
|
||||
output = subprocess.check_output(['fastfetch', '--help-raw'], stderr=subprocess.DEVNULL)
|
||||
data = json.loads(output)
|
||||
|
||||
for category in data.values():
|
||||
for flag in category:
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
if "short" in flag:
|
||||
print(f"-{flag['short']}")
|
||||
|
||||
if "long" in flag:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
for i in range(1, 10):
|
||||
print(f"--logo-color-{i}")
|
||||
else:
|
||||
print(f"--{flag['long']}")
|
||||
except Exception:
|
||||
# If error occurs, return no options
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1])
|
||||
EOF
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${opts[*]}" -- "$cur"))
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__fastfetch_complete_bool()
|
||||
{
|
||||
COMPREPLY=($(compgen -W "true false" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_string()
|
||||
{
|
||||
if [[ $CURRENT_WORD != "" ]]; then
|
||||
COMPREPLY=("$CURRENT_WORD")
|
||||
fi
|
||||
}
|
||||
|
||||
__fastfetch_complete_path()
|
||||
{
|
||||
COMPREPLY=($(compgen -A file -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_logo()
|
||||
{
|
||||
COMPREPLY=($(compgen -W "$(fastfetch --list-logos autocompletion)" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_logo_type()
|
||||
{
|
||||
local __ff_logo_types=(
|
||||
"auto"
|
||||
"builtin"
|
||||
"file"
|
||||
"raw"
|
||||
"sixel"
|
||||
"kitty"
|
||||
"chafa"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_logo_types[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_binary_prefix()
|
||||
{
|
||||
local __ff_size_binary_prefixes=(
|
||||
"iec"
|
||||
"si"
|
||||
"jedec"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_size_binary_prefixes[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_gl()
|
||||
{
|
||||
local __ff_gl_types=(
|
||||
"auto"
|
||||
"egl"
|
||||
"glx"
|
||||
"osmesa"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_gl_types[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_option()
|
||||
{
|
||||
local FF_OPTIONS_ALL=(
|
||||
"${FF_OPTIONS_BOOL[@]}"
|
||||
"${FF_OPTIONS_STRING[@]}"
|
||||
"${FF_OPTIONS_PATH[@]}"
|
||||
"${FF_OPTIONS_LOGO[@]}"
|
||||
"${FF_OPTIONS_LOGO_TYPE[@]}"
|
||||
"${FF_OPTIONS_BINARY_PREFIX[@]}"
|
||||
"${FF_OPTIONS_OPENGL[@]}"
|
||||
)
|
||||
|
||||
if [[ $WORD_COUND -lt 3 ]]; then
|
||||
FF_OPTIONS_ALL+=(
|
||||
"${FF_OPTIONS_SINGLE[@]}"
|
||||
"${FF_OPTIONS_HELP[@]}"
|
||||
)
|
||||
fi
|
||||
|
||||
for ff_word in ${COMP_WORDS[@]}; do
|
||||
if [[ $ff_word == $CURRENT_WORD ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
FF_OPTIONS_ALL=("${FF_OPTIONS_ALL[@]/$ff_word}")
|
||||
done
|
||||
|
||||
COMPREPLY=($(compgen -W "${FF_OPTIONS_ALL[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_previous_matches()
|
||||
{
|
||||
for ff_option in "$@"; do
|
||||
if [[ $ff_option == "$PREVIOUS_WORD" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
__fastfetch_completion()
|
||||
{
|
||||
local CURRENT_WORD="${COMP_WORDS[$COMP_CWORD]}"
|
||||
local PREVIOUS_WORD="${COMP_WORDS[$COMP_CWORD - 1]}"
|
||||
local WORD_COUND="${#COMP_WORDS[@]}"
|
||||
|
||||
local FF_OPTIONS_SINGLE=(
|
||||
"-v"
|
||||
"--version"
|
||||
"--list-logos"
|
||||
"--list-modules"
|
||||
"--list-presets"
|
||||
"--list-features"
|
||||
"--print-logos"
|
||||
"--print-config-system"
|
||||
"--print-config-user"
|
||||
"--print-structure"
|
||||
"--gen-config"
|
||||
"--gen-config-force"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_HELP=(
|
||||
"-h"
|
||||
"--help"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_BOOL=(
|
||||
"-r"
|
||||
"--show-errors"
|
||||
"--logo-print-remaining"
|
||||
"--multithreading"
|
||||
"--stat"
|
||||
"--allow-slow-operations"
|
||||
"--disable-linewrap"
|
||||
"--hide-cursor"
|
||||
"--cpu-temp"
|
||||
"--gpu-temp"
|
||||
"--battery-temp"
|
||||
"--display-precise-refresh-rate"
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-flags"
|
||||
"--localip-show-loop"
|
||||
"--localip-show-mtu"
|
||||
"--localip-show-speed"
|
||||
"--localip-name-prefix"
|
||||
"--localip-compact-type"
|
||||
"--escape-bedrock"
|
||||
"--pipe"
|
||||
"--title-fqdn"
|
||||
"--disk-folders"
|
||||
"--disk-show-external"
|
||||
"--disk-show-hidden"
|
||||
"--disk-show-subvolumes"
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--gpu-force-method"
|
||||
"--disk-show-unknown"
|
||||
"--bluetooth-show-disconnected"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
"--logo-type"
|
||||
"--logo-padding"
|
||||
"--logo-padding-left"
|
||||
"--logo-padding-right"
|
||||
"--logo-padding-top"
|
||||
"--logo-color-1"
|
||||
"--logo-color-2"
|
||||
"--logo-color-3"
|
||||
"--logo-color-4"
|
||||
"--logo-color-5"
|
||||
"--logo-color-6"
|
||||
"--logo-color-7"
|
||||
"--logo-color-8"
|
||||
"--logo-color-9"
|
||||
"--logo-width"
|
||||
"--logo-height"
|
||||
"--color"
|
||||
"--color-keys"
|
||||
"--color-title"
|
||||
"--display-compact-type"
|
||||
"--separator"
|
||||
"-s"
|
||||
"--structure"
|
||||
"--player-name"
|
||||
"--percent-type"
|
||||
"--publicip-url"
|
||||
"--publicip-timeout"
|
||||
"--weather-output-format"
|
||||
"--weather-timeout"
|
||||
"--os-key"
|
||||
"--os-format"
|
||||
"--os-key-color"
|
||||
"--host-key"
|
||||
"--host-format"
|
||||
"--host-key-color"
|
||||
"--kernel-key"
|
||||
"--kernel-format"
|
||||
"--kernel-key-color"
|
||||
"--uptime-key"
|
||||
"--uptime-format"
|
||||
"--uptime-key-color"
|
||||
"--processes-key"
|
||||
"--processes-format"
|
||||
"--processes-key-color"
|
||||
"--packages-key"
|
||||
"--packages-format"
|
||||
"--packages-key-color"
|
||||
"--shell-key"
|
||||
"--shell-format"
|
||||
"--shell-key-color"
|
||||
"--display-key"
|
||||
"--display-format"
|
||||
"--display-key-color"
|
||||
"--de-key"
|
||||
"--de-format"
|
||||
"--de-key-color"
|
||||
"--wm-key"
|
||||
"--wm-format"
|
||||
"--wm-key-color"
|
||||
"--wmtheme-key"
|
||||
"--wmtheme-format"
|
||||
"--wmtheme-key-color"
|
||||
"--theme-key"
|
||||
"--theme-format"
|
||||
"--theme-key-color"
|
||||
"--icons-key"
|
||||
"--icons-format"
|
||||
"--icons-key-color"
|
||||
"--font-key"
|
||||
"--font-format"
|
||||
"--font-key-color"
|
||||
"--cursor-key"
|
||||
"--cursor-format"
|
||||
"--cursor-key-color"
|
||||
"--terminal-key"
|
||||
"--terminal-format"
|
||||
"--terminal-key-color"
|
||||
"--terminalfont-key"
|
||||
"--terminalfont-format"
|
||||
"--terminalfont-key-color"
|
||||
"--cpu-key"
|
||||
"--cpu-format"
|
||||
"--cpu-key-color"
|
||||
"--cpu-useage-key"
|
||||
"--cpu-useage-format"
|
||||
"--cpu-useage-key-color"
|
||||
"--gpu-key"
|
||||
"--gpu-format"
|
||||
"--gpu-key-color"
|
||||
"--memory-key"
|
||||
"--memory-format"
|
||||
"--memory-key-color"
|
||||
"--swap-key"
|
||||
"--swap-format"
|
||||
"--swap-key-color"
|
||||
"--disk-key"
|
||||
"--disk-format"
|
||||
"--disk-key-color"
|
||||
"--battery-key"
|
||||
"--battery-format"
|
||||
"--battery-key-color"
|
||||
"--poweradapter-key"
|
||||
"--poweradapter-format"
|
||||
"--poweradapter-key-color"
|
||||
"--locale-key"
|
||||
"--locale-format"
|
||||
"--locale-key-color"
|
||||
"--localip-key"
|
||||
"--localip-format"
|
||||
"--localip-key-color"
|
||||
"--publicip-key"
|
||||
"--publicip-format"
|
||||
"--publicip-key-color"
|
||||
"--wifi-key"
|
||||
"--wifi-format"
|
||||
"--wifi-key-color"
|
||||
"--weather-key"
|
||||
"--weather-format"
|
||||
"--weather-key-color"
|
||||
"--player-key"
|
||||
"--player-format"
|
||||
"--player-key-color"
|
||||
"--media-key"
|
||||
"--media-format"
|
||||
"--media-key-color"
|
||||
"--datetime-key"
|
||||
"--datetime-format"
|
||||
"--datetime-key-color"
|
||||
"--date-key"
|
||||
"--date-format"
|
||||
"--date-key-color"
|
||||
"--time-key"
|
||||
"--time-format"
|
||||
"--time-key-color"
|
||||
"--vulkan-key"
|
||||
"--vulkan-format"
|
||||
"--vulkan-key-color"
|
||||
"--opengl-key"
|
||||
"--opengl-format"
|
||||
"--opengl-key-color"
|
||||
"--opencl-key"
|
||||
"--opencl-format"
|
||||
"--opencl-key-color"
|
||||
"--users-key"
|
||||
"--users-format"
|
||||
"--users-key-color"
|
||||
"--users-myself-only"
|
||||
"--bluetooth-key"
|
||||
"--bluetooth-format"
|
||||
"--bluetooth-key-color"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
"-c"
|
||||
"--config"
|
||||
"--lib-vulkan"
|
||||
"--lib-wayland"
|
||||
"--lib-xcb-randr"
|
||||
"--lib-xcb"
|
||||
"--lib-xrandr"
|
||||
"--lib-X11"
|
||||
"--lib-gio"
|
||||
"--lib-dconf"
|
||||
"--lib-dbus"
|
||||
"--lib-xfconf"
|
||||
"--lib-sqlite3"
|
||||
"--lib-rpm"
|
||||
"--lib-imagemagick"
|
||||
"--lib-z"
|
||||
"--lib-chafa"
|
||||
"--lib-egl"
|
||||
"--lib-glx"
|
||||
"--lib-osmesa"
|
||||
"--lib-opencl"
|
||||
"--lib-pulse"
|
||||
"--lib-ddcutil"
|
||||
"--lib-nm"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO=(
|
||||
"-l"
|
||||
"--logo"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO_TYPE=(
|
||||
"--logo-type"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_BINARY_PREFIX=(
|
||||
"--binary-prefix"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_OPENGL=(
|
||||
"--opengl-type"
|
||||
)
|
||||
|
||||
if __fastfetch_previous_matches "${FF_OPTIONS_SINGLE[@]}"; then
|
||||
return
|
||||
elif [[ $WORD_COUND -gt 3 && ( ${COMP_WORDS[$COMP_CWORD - 2]} == "--help" || ${COMP_WORDS[$COMP_CWORD - 2]} == "-h" ) ]]; then
|
||||
return
|
||||
elif [[ $CURRENT_WORD == "-"* ]]; then
|
||||
__fastfetch_complete_option
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_HELP[@]}"; then
|
||||
__fastfetch_complete_help
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_BOOL[@]}"; then
|
||||
__fastfetch_complete_bool
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_STRING[@]}"; then
|
||||
__fastfetch_complete_string
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_PATH[@]}"; then
|
||||
__fastfetch_complete_path
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO[@]}"; then
|
||||
__fastfetch_complete_logo
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO_TYPE[@]}"; then
|
||||
__fastfetch_complete_logo_type
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_BINARY_PREFIX[@]}"; then
|
||||
__fastfetch_complete_binary_prefix
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_OPENGL[@]}"; then
|
||||
__fastfetch_complete_gl
|
||||
else
|
||||
__fastfetch_complete_option
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F __fastfetch_completion fastfetch
|
||||
# Register completion
|
||||
complete -F _fastfetch fastfetch
|
||||
|
||||
Vendored
+42
@@ -1,3 +1,45 @@
|
||||
fastfetch (2.39.0ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Remove unwanted debugging code
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:39:22 +0800
|
||||
|
||||
fastfetch (2.39.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.39.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:35:18 +0800
|
||||
|
||||
fastfetch (2.38.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.38.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 05 Mar 2025 14:56:24 +0800
|
||||
|
||||
fastfetch (2.37.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.37.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 19 Feb 2025 15:43:42 +0800
|
||||
|
||||
fastfetch (2.36.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.36.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 11 Feb 2025 13:39:55 +0800
|
||||
|
||||
fastfetch (2.36.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.36.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 10 Feb 2025 10:13:53 +0800
|
||||
|
||||
fastfetch (2.35.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.35.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Sun, 26 Jan 2025 10:15:22 +0800
|
||||
|
||||
fastfetch (2.34.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.34.1
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.34.1_source.buildinfo universe/utils optional
|
||||
fastfetch_2.39.0ubuntu1_source.buildinfo universe/utils optional
|
||||
|
||||
+11
-10
@@ -179,11 +179,11 @@
|
||||
"type": "string"
|
||||
},
|
||||
"displayFormat": {
|
||||
"description": "Output format of the module `Display`. See `-h format` for formatting syntax\n 1. {width}: Screen configured width (in pixels)\n 2. {height}: Screen configured height (in pixels)\n 3. {refresh-rate}: Screen configured refresh rate (in Hz)\n 4. {scaled-width}: Screen scaled width (in pixels)\n 5. {scaled-height}: Screen scaled height (in pixels)\n 6. {name}: Screen name\n 7. {type}: Screen type (builtin, external or unknown)\n 8. {rotation}: Screen rotation (in degrees)\n 9. {is-primary}: True if being the primary screen\n 10. {physical-width}: Screen physical width (in millimeters)\n 11. {physical-height}: Screen physical height (in millimeters)\n 12. {inch}: Physical diagonal length in inches\n 13. {ppi}: Pixels per inch (PPI)\n 14. {bit-depth}: Bits per color channel\n 15. {hdr-enabled}: True if high dynamic range (HDR) mode is enabled\n 16. {manufacture-year}: Year of manufacturing\n 17. {manufacture-week}: Nth week of manufacturing in the year\n 18. {serial}: Serial number\n 19. {platform-api}: The platform API used when detecting the display\n 20. {hdr-compatible}: True if the display is HDR compatible\n 21. {scale-factor}: HiDPI scale factor\n 22. {preferred-width}: Screen preferred width (in pixels)\n 23. {preferred-height}: Screen preferred height (in pixels)\n 24. {preferred-refresh-rate}: Screen preferred refresh rate (in Hz)",
|
||||
"description": "Output format of the module `Display`. See `-h format` for formatting syntax\n 1. {width}: Screen configured width (in pixels)\n 2. {height}: Screen configured height (in pixels)\n 3. {refresh-rate}: Screen configured refresh rate (in Hz)\n 4. {scaled-width}: Screen scaled width (in pixels)\n 5. {scaled-height}: Screen scaled height (in pixels)\n 6. {name}: Screen name\n 7. {type}: Screen type (Built-in or External)\n 8. {rotation}: Screen rotation (in degrees)\n 9. {is-primary}: True if being the primary screen\n 10. {physical-width}: Screen physical width (in millimeters)\n 11. {physical-height}: Screen physical height (in millimeters)\n 12. {inch}: Physical diagonal length in inches\n 13. {ppi}: Pixels per inch (PPI)\n 14. {bit-depth}: Bits per color channel\n 15. {hdr-enabled}: True if high dynamic range (HDR) mode is enabled\n 16. {manufacture-year}: Year of manufacturing\n 17. {manufacture-week}: Nth week of manufacturing in the year\n 18. {serial}: Serial number\n 19. {platform-api}: The platform API used when detecting the display\n 20. {hdr-compatible}: True if the display is HDR compatible\n 21. {scale-factor}: HiDPI scale factor\n 22. {preferred-width}: Screen preferred width (in pixels)\n 23. {preferred-height}: Screen preferred height (in pixels)\n 24. {preferred-refresh-rate}: Screen preferred refresh rate (in Hz)",
|
||||
"type": "string"
|
||||
},
|
||||
"diskFormat": {
|
||||
"description": "Output format of the module `Disk`. See `-h format` for formatting syntax\n 1. {size-used}: Size used\n 2. {size-total}: Size total\n 3. {size-percentage}: Size percentage num\n 4. {files-used}: Files used\n 5. {files-total}: Files total\n 6. {files-percentage}: Files percentage num\n 7. {is-external}: True if external volume\n 8. {is-hidden}: True if hidden volume\n 9. {filesystem}: Filesystem\n 10. {name}: Label / name\n 11. {is-readonly}: True if read-only\n 12. {create-time}: Create time in local timezone\n 13. {size-percentage-bar}: Size percentage bar\n 14. {files-percentage-bar}: Files percentage bar\n 15. {days}: Days after creation\n 16. {hours}: Hours after creation\n 17. {minutes}: Minutes after creation\n 18. {seconds}: Seconds after creation\n 19. {milliseconds}: Milliseconds after creation",
|
||||
"description": "Output format of the module `Disk`. See `-h format` for formatting syntax\n 1. {size-used}: Size used\n 2. {size-total}: Size total\n 3. {size-percentage}: Size percentage num\n 4. {files-used}: Files used\n 5. {files-total}: Files total\n 6. {files-percentage}: Files percentage num\n 7. {is-external}: True if external volume\n 8. {is-hidden}: True if hidden volume\n 9. {filesystem}: Filesystem\n 10. {name}: Label / name\n 11. {is-readonly}: True if read-only\n 12. {create-time}: Create time in local timezone\n 13. {size-percentage-bar}: Size percentage bar\n 14. {files-percentage-bar}: Files percentage bar\n 15. {days}: Days after creation\n 16. {hours}: Hours after creation\n 17. {minutes}: Minutes after creation\n 18. {seconds}: Seconds after creation\n 19. {milliseconds}: Milliseconds after creation\n 20. {mountpoint}: Mount point / drive letter\n 21. {mount-from}: Mount from (device path)",
|
||||
"type": "string"
|
||||
},
|
||||
"diskioFormat": {
|
||||
@@ -207,7 +207,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"gpuFormat": {
|
||||
"description": "Output format of the module `GPU`. See `-h format` for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index",
|
||||
"description": "Output format of the module `GPU`. See `-h format` for formatting syntax\n 1. {vendor}: GPU vendor\n 2. {name}: GPU name\n 3. {driver}: GPU driver\n 4. {temperature}: GPU temperature\n 5. {core-count}: GPU core count\n 6. {type}: GPU type\n 7. {dedicated-total}: GPU total dedicated memory\n 8. {dedicated-used}: GPU used dedicated memory\n 9. {shared-total}: GPU total shared memory\n 10. {shared-used}: GPU used shared memory\n 11. {platform-api}: The platform API used when detecting the GPU\n 12. {frequency}: Current frequency in GHz\n 13. {index}: GPU vendor specific index\n 14. {dedicated-percentage-num}: Dedicated memory usage percentage num\n 15. {dedicated-percentage-bar}: Dedicated memory usage percentage bar\n 16. {shared-percentage-num}: Shared memory usage percentage num\n 17. {shared-percentage-bar}: Shared memory usage percentage bar\n 18. {core-usage-num}: Core usage percentage num (supports Nvidia & Apple GPU only)\n 19. {core-usage-bar}: Core usage percentage bar (supports Nvidia & Apple GPU only)",
|
||||
"type": "string"
|
||||
},
|
||||
"hostFormat": {
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"packagesFormat": {
|
||||
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {nix-all}: Total number of all nix packages\n 40. {flatpak-all}: Total number of all flatpak app packages\n 41. {brew-all}: Total number of all brew packages\n 42. {guix-all}: Total number of all guix packages",
|
||||
"description": "Output format of the module `Packages`. See `-h format` for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {nix-all}: Total number of all nix packages\n 43. {flatpak-all}: Total number of all flatpak app packages\n 44. {brew-all}: Total number of all brew packages\n 45. {guix-all}: Total number of all guix packages\n 46. {hpkg-all}: Total number of all hpkg packages",
|
||||
"type": "string"
|
||||
},
|
||||
"physicaldiskFormat": {
|
||||
@@ -786,11 +786,11 @@
|
||||
},
|
||||
{
|
||||
"const": "si",
|
||||
"description": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ..."
|
||||
"description": "1000 Bytes = 1 kB, 1000 kB = 1 MB, ..."
|
||||
},
|
||||
{
|
||||
"const": "jedec",
|
||||
"description": "1024 Bytes = 1 kB, 1024 K = 1 MB, ..."
|
||||
"description": "1024 Bytes = 1 KB, 1024 KB = 1 MB, ..."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -817,8 +817,8 @@
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"description": "Set the unit of the temperature",
|
||||
"enum": ["CELSIUS", "C", "FAHRENHEIT", "F", "KELVIN", "K"],
|
||||
"default": "C"
|
||||
"enum": ["D", "Default", "Celsius", "C", "Fahrenheit", "F", "Kelvin", "K"],
|
||||
"default": "D"
|
||||
},
|
||||
"ndigits": {
|
||||
"type": "integer",
|
||||
@@ -2563,8 +2563,7 @@
|
||||
"enum": [
|
||||
"auto",
|
||||
"egl",
|
||||
"glx",
|
||||
"osmesa"
|
||||
"glx"
|
||||
],
|
||||
"default": "auto"
|
||||
},
|
||||
@@ -2641,6 +2640,7 @@
|
||||
"eopkg",
|
||||
"flatpak",
|
||||
"guix",
|
||||
"hpkg",
|
||||
"linglong",
|
||||
"lpkg",
|
||||
"lpkgbuild",
|
||||
@@ -2651,6 +2651,7 @@
|
||||
"pacman",
|
||||
"pacstall",
|
||||
"paludis",
|
||||
"pisi",
|
||||
"pkg",
|
||||
"pkgtool",
|
||||
"qi",
|
||||
|
||||
@@ -90,6 +90,8 @@
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
|
||||
@@ -92,6 +92,8 @@
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
// Based on #1576
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
"color": {
|
||||
"keys": "blue"
|
||||
},
|
||||
"separator": "",
|
||||
"constants": [
|
||||
"──────────────────────────────────────────────",
|
||||
"\u001b[47D",
|
||||
"\u001b[47C",
|
||||
"\u001b[46C"
|
||||
],
|
||||
"brightColor": false
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "version",
|
||||
"key": "┌───────────────┬─{$1}┐\u001b[41D",
|
||||
"format": "\u001b[1m{#keys} {1} - {2} "
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "│ {icon} Fetched │{$3}│{$2}",
|
||||
"format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {timezone-name}"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"key": "│ {icon} Locale │{$3}│{$2}"
|
||||
},
|
||||
|
||||
// Hardware
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_cyan} Hardware "
|
||||
},
|
||||
{
|
||||
"type": "chassis",
|
||||
"key": "│{#cyan}│ {icon} Chassis │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│{#cyan}│ {icon} RAM │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│{#cyan}│ {icon} SWAP │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│{#cyan}│ {icon} CPU │{$4}│{#keys}│{$2}",
|
||||
"showPeCoreCount": true
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#cyan}│ {icon} GPU │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│{#cyan}│ {icon} Disk │{$4}│{#keys}│{$2}",
|
||||
"format": "{size-used} \/ {size-total} ({size-percentage}) - {filesystem}",
|
||||
},
|
||||
{
|
||||
"type": "battery",
|
||||
"key": "│{#cyan}│ {icon} Battery │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Desktop
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_green} Desktop "
|
||||
},
|
||||
{
|
||||
"type": "de",
|
||||
"key": "│{#green}│ {icon} Desktop │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "│{#green}│ {icon} Session │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "display",
|
||||
"key": "│{#green}│ {icon} Display │{$4}│{#keys}│{$2}",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#green}│ {icon} G-Driver │{$4}│{#keys}│{$2}",
|
||||
"format": "{driver}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Terminal
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_yellow} Terminal "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "│{#yellow}│ {icon} Shell │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│{#yellow}│ {icon} Terminal │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "│{#yellow}│ {icon} Term Font │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminaltheme",
|
||||
"key": "│{#yellow}│ {icon} Colors │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│{#yellow}│ {icon} Packages │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Development
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}┌──────────────┬{$1}┐{#keys}│\u001b[39D",
|
||||
"format": "{#bright_red} Development "
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Rust │{$4}│{#keys}│{$2}",
|
||||
"text": "rustc --version | cut -d' ' -f2",
|
||||
"format": "rustc {}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"text": "clang --version | head -1 | awk '{print $NF}'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} NodeJS │{$4}│{#keys}│{$2}",
|
||||
"text": "node --version",
|
||||
"format": "node {~1}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Go │{$4}│{#keys}│{$2}",
|
||||
"text": "go version | cut -d' ' -f3",
|
||||
"format": "go {~2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Zig │{$4}│{#keys}│{$2}",
|
||||
"text": "zig version",
|
||||
"format": "zig {}"
|
||||
},
|
||||
{
|
||||
"type": "editor",
|
||||
"key": "│{#red}│ {icon} Editor │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Git │{$4}│{#keys}│{$2}",
|
||||
"text": "git version",
|
||||
"format": "git {~12}"
|
||||
},
|
||||
{
|
||||
"type": "font",
|
||||
"key": "│{#red}│ {icon} Interface │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Uptime
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}┌──────────────┬{$1}┐{#keys}│\u001b[36D",
|
||||
"format": "{#bright_magenta} Uptime "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│{#magenta}│ {icon} Uptime │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"myselfOnly": true,
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"folders": "/", // On macOS, "/System/Volumes/VM" works for me
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "└─────────────────{$1}┘",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// End
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
}
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
def main(amdgpu_ids_path: str):
|
||||
with open(amdgpu_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
products = []
|
||||
for line in full_text.split('\n'):
|
||||
if not line or line[0] == '#' or not ',\t' in line:
|
||||
continue
|
||||
device, revision, name = line.split(',\t', maxsplit=2)
|
||||
products.append((device, revision, name))
|
||||
|
||||
code = """\
|
||||
// SPDX-License-Identifier: MIT
|
||||
// https://opensource.org/license/mit
|
||||
// Generated from https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct FFArmGpuProduct
|
||||
{
|
||||
const uint32_t id; // device << 8 | revision
|
||||
const char* name;
|
||||
} FFArmGpuProduct;
|
||||
|
||||
const FFArmGpuProduct ffAmdGpuProducts[] = {
|
||||
"""
|
||||
|
||||
for device, revision, name in products:
|
||||
code += f" {{ 0x{device} << 8 | 0x{revision}, \"{name}\" }},\n"
|
||||
|
||||
code += "};\n"
|
||||
|
||||
print(code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
len(sys.argv) == 2 or sys.exit('Usage: gen-amdgpuids.py </path/to/amdgpu.ids>')
|
||||
|
||||
main(sys.argv[1])
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from requests import get as http_get
|
||||
import sys
|
||||
|
||||
class PciDeviceModel:
|
||||
def __init__(self, id: int, name: str):
|
||||
@@ -13,14 +13,10 @@ class PciVendorModel:
|
||||
self.name = name
|
||||
self.devices = []
|
||||
|
||||
def main(keep_vendor_list: set):
|
||||
def main(keep_vendor_list: set, pci_ids_path: str):
|
||||
vendors = []
|
||||
try:
|
||||
with open('pci.ids', 'r') as f:
|
||||
full_text = f.read()
|
||||
except FileNotFoundError:
|
||||
response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids')
|
||||
full_text = response.text
|
||||
with open(pci_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
|
||||
for line in dev_list_text.split('\n'):
|
||||
@@ -80,6 +76,8 @@ const FFPciVendor ffPciVendors[] = {{
|
||||
print(code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
len(sys.argv) == 2 or sys.exit('Usage: gen-pciids.py </path/to/pci.ids>')
|
||||
|
||||
# From <src/detection/gpu/gpu.c>
|
||||
main({
|
||||
0x106b, # Apple
|
||||
@@ -94,4 +92,4 @@ if __name__ == '__main__':
|
||||
0x1ab8, # Parallel
|
||||
0x1414, # Microsoft
|
||||
0x108e, # Oracle
|
||||
})
|
||||
}, sys.argv[1])
|
||||
|
||||
+20
-11
@@ -259,24 +259,33 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
continue;
|
||||
}
|
||||
|
||||
//test for constant, if so evaluate it
|
||||
//test for constant or env var, if so evaluate it
|
||||
if (firstChar == '$')
|
||||
{
|
||||
char* pend = NULL;
|
||||
int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10);
|
||||
uint32_t index = (uint32_t) indexSigned;
|
||||
bool backward = indexSigned < 0;
|
||||
|
||||
if (indexSigned == 0 || *pend != '\0' || instance.config.display.constants.length < index)
|
||||
if (pend == placeholderValue.chars + 1)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
// treat placeholder as an environment variable
|
||||
char* envValue = getenv(placeholderValue.chars + 1);
|
||||
if (envValue)
|
||||
ffStrbufAppendS(buffer, envValue);
|
||||
else
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// treat placeholder as a constant
|
||||
uint32_t index = (uint32_t) (indexSigned < 0 ? (int32_t) instance.config.display.constants.length + indexSigned : indexSigned - 1);
|
||||
|
||||
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, backward
|
||||
? instance.config.display.constants.length - index
|
||||
: index - 1);
|
||||
ffStrbufAppend(buffer, item);
|
||||
if (*pend != '\0' || instance.config.display.constants.length <= index)
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
else
|
||||
{
|
||||
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, index);
|
||||
ffStrbufAppend(buffer, item);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -227,15 +227,15 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_GLX
|
||||
"glx\n"
|
||||
#endif
|
||||
#if FF_HAVE_OSMESA
|
||||
"osmesa\n"
|
||||
#endif
|
||||
#if FF_HAVE_OPENCL
|
||||
"opencl\n"
|
||||
#endif
|
||||
#if FF_HAVE_FREETYPE
|
||||
"freetype\n"
|
||||
#endif
|
||||
#if FF_HAVE_PCIACCESS
|
||||
"libpciaccess\n"
|
||||
#endif
|
||||
#if FF_HAVE_PULSE
|
||||
"libpulse\n"
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if __APPLE__ // #1395
|
||||
#if (__APPLE__ || __HAIKU__) // #1395
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
|
||||
@@ -310,7 +310,7 @@ void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indenta
|
||||
continue;
|
||||
|
||||
bool isDir = false;
|
||||
#ifndef __sun
|
||||
#if !defined(__sun) && !defined(__HAIKU__)
|
||||
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
|
||||
isDir = entry->d_type == DT_DIR;
|
||||
else
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef _WIN32
|
||||
#include <net/if.h>
|
||||
#else
|
||||
#define IF_NAMESIZE 16
|
||||
#define IF_NAMESIZE 0
|
||||
#endif
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "netif.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
@@ -8,13 +9,17 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#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__)
|
||||
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__OpenBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
@@ -47,6 +52,39 @@ get_rt_address(struct rt_msghdr *rtm, int desired)
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
#if defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY};
|
||||
size_t needed;
|
||||
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE char* buf = malloc(needed);
|
||||
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
||||
return false;
|
||||
|
||||
char* lim = buf + needed;
|
||||
struct rt_msghdr* rtm;
|
||||
for (char* next = buf; next < lim; next += rtm->rtm_msglen)
|
||||
{
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
struct sockaddr* sa = (struct sockaddr *)(rtm + 1);
|
||||
|
||||
if ((rtm->rtm_flags & RTF_GATEWAY) && (sa->sa_family == AF_INET))
|
||||
{
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP);
|
||||
if (sdl->sdl_family == AF_LINK)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
//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);
|
||||
@@ -106,5 +144,7 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// loosely based on Haiku's src/bin/network/route/route.cpp
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
// TODO: AF_INET6
|
||||
FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET);
|
||||
if (pfRoute < 0)
|
||||
return false;
|
||||
|
||||
struct ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
|
||||
return false;
|
||||
|
||||
int size = config.ifc_value;
|
||||
if (size <= 0)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE void *buffer = malloc((size_t) size);
|
||||
if (buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config.ifc_len = size;
|
||||
config.ifc_buf = buffer;
|
||||
if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0)
|
||||
return false;
|
||||
|
||||
struct ifreq *interface = (struct ifreq*)buffer;
|
||||
struct ifreq *end = (struct ifreq*)((uint8_t*)buffer + size);
|
||||
|
||||
while (interface < end) {
|
||||
if (interface->ifr_route.flags & RTF_DEFAULT) {
|
||||
strlcpy(iface, interface->ifr_name, IF_NAMESIZE);
|
||||
*ifIndex = if_nametoindex(interface->ifr_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t addressSize = 0;
|
||||
if (interface->ifr_route.destination != NULL)
|
||||
addressSize += interface->ifr_route.destination->sa_len;
|
||||
if (interface->ifr_route.mask != NULL)
|
||||
addressSize += interface->ifr_route.mask->sa_len;
|
||||
if (interface->ifr_route.gateway != NULL)
|
||||
addressSize += interface->ifr_route.gateway->sa_len;
|
||||
|
||||
interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE
|
||||
+ sizeof(struct route_entry) + addressSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,27 +1,36 @@
|
||||
#include "netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <ws2tcpip.h> // AF_INET6, IN6_IS_ADDR_UNSPECIFIED
|
||||
#include <iphlpapi.h>
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char* iface/* unsupported */, uint32_t* ifIndex)
|
||||
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
PMIB_IPFORWARD_TABLE2 pIpForwardTable = NULL;
|
||||
DWORD result = GetIpForwardTable2(AF_UNSPEC, &pIpForwardTable);
|
||||
|
||||
if (result != NO_ERROR)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
|
||||
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
|
||||
return false;
|
||||
bool foundDefault = false;
|
||||
|
||||
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
|
||||
for (ULONG i = 0; i < pIpForwardTable->NumEntries; ++i)
|
||||
{
|
||||
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
|
||||
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
|
||||
MIB_IPFORWARD_ROW2* row = &pIpForwardTable->Table[i];
|
||||
|
||||
if ((row->DestinationPrefix.PrefixLength == 0) &&
|
||||
((row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET &&
|
||||
row->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr == 0) ||
|
||||
(row->DestinationPrefix.Prefix.Ipv6.sin6_family == AF_INET6 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr))))
|
||||
{
|
||||
*ifIndex = ipForwardRow->dwForwardIfIndex;
|
||||
*ifIndex = row->InterfaceIndex;
|
||||
foundDefault = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
FreeMibTable(pIpForwardTable);
|
||||
|
||||
return foundDefault;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
#include <minwindef.h>
|
||||
#endif
|
||||
|
||||
struct addrinfo;
|
||||
|
||||
typedef struct FFNetworkingState {
|
||||
#ifdef _WIN32
|
||||
uintptr_t sockfd;
|
||||
OVERLAPPED overlapped;
|
||||
#else
|
||||
int sockfd;
|
||||
FFstrbuf host;
|
||||
FFstrbuf command;
|
||||
struct addrinfo* addr;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
FFThreadType thread;
|
||||
@@ -23,7 +25,14 @@ typedef struct FFNetworkingState {
|
||||
|
||||
uint32_t timeout;
|
||||
bool ipv6;
|
||||
bool compression; // if true, HTTP content compression will be enabled if supported
|
||||
bool tfo; // if true, TCP Fast Open will be attempted first, and fallback to traditional connection if it fails
|
||||
} FFNetworkingState;
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer);
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* ffNetworkingLoadZlibLibrary(void);
|
||||
bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd);
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/library.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
|
||||
struct FFZlibLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(inflateInit2_)
|
||||
FF_LIBRARY_SYMBOL(inflate)
|
||||
FF_LIBRARY_SYMBOL(inflateEnd)
|
||||
FF_LIBRARY_SYMBOL(inflateGetHeader)
|
||||
|
||||
bool inited;
|
||||
} zlibData;
|
||||
|
||||
const char* ffNetworkingLoadZlibLibrary(void)
|
||||
{
|
||||
if (!zlibData.inited)
|
||||
{
|
||||
zlibData.inited = true;
|
||||
FF_LIBRARY_LOAD(zlib, "dlopen libz failed",
|
||||
#ifdef _WIN32
|
||||
"zlib1"
|
||||
#else
|
||||
"libz"
|
||||
#endif
|
||||
FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateInit2_)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflate)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateEnd)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateGetHeader)
|
||||
zlib = NULL; // don't auto dlclose
|
||||
}
|
||||
return zlibData.ffinflateEnd == NULL ? "Failed to load libz" : NULL;
|
||||
}
|
||||
|
||||
// Try to pre-read gzip header to determine uncompressed size
|
||||
static uint32_t guessGzipOutputSize(const void* data, uint32_t dataSize)
|
||||
{
|
||||
// gzip file format: http://www.zlib.org/rfc-gzip.html
|
||||
if (dataSize < 10 || ((const uint8_t*)data)[0] != 0x1f || ((const uint8_t*)data)[1] != 0x8b)
|
||||
return 0;
|
||||
|
||||
// Uncompressed size in gzip format is stored in the last 4 bytes, but only valid if data is less than 4GB
|
||||
if (dataSize > 18) {
|
||||
// Get ISIZE value from the end of file (little endian)
|
||||
const uint8_t* tail = (const uint8_t*)data + dataSize - 4;
|
||||
uint32_t uncompressedSize = (uint32_t) tail[0] | ((uint32_t) tail[1] << 8u) | ((uint32_t) tail[2] << 16u) | ((uint32_t) tail[3] << 24u);
|
||||
|
||||
// For valid gzip files, this value is the length of the uncompressed data modulo 2^32
|
||||
if (uncompressedSize > 0) {
|
||||
FF_DEBUG("Read uncompressed size from GZIP trailer: %u bytes", uncompressedSize);
|
||||
// Add some margin to the estimated size for safety
|
||||
return uncompressedSize + 64;
|
||||
}
|
||||
}
|
||||
|
||||
// If unable to get size from trailer or size is 0, use estimated value
|
||||
// Typically, text data compression ratio is between 3-5x, we use the larger value
|
||||
uint32_t estimatedSize = dataSize * 5;
|
||||
FF_DEBUG("Unable to read exact uncompressed size, estimated as 5x of compressed data: %u bytes", estimatedSize);
|
||||
return estimatedSize;
|
||||
}
|
||||
|
||||
// Decompress gzip content
|
||||
bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
{
|
||||
// Calculate header size
|
||||
uint32_t headerSize = (uint32_t) (headerEnd - buffer->chars);
|
||||
|
||||
*headerEnd = '\0'; // Replace delimiter with null character for easier processing
|
||||
// Ensure Content-Encoding is in response headers, not in response body
|
||||
bool hasGzip = strcasestr(buffer->chars, "\nContent-Encoding: gzip") != NULL;
|
||||
*headerEnd = '\r'; // Restore delimiter
|
||||
|
||||
if (!hasGzip) {
|
||||
FF_DEBUG("No gzip compressed content detected, skipping decompression");
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_DEBUG("Gzip compressed content detected, preparing for decompression");
|
||||
|
||||
const char* bodyStart = headerEnd + 4; // Skip delimiter
|
||||
|
||||
// Calculate compressed content size
|
||||
uint32_t compressedSize = buffer->length - headerSize - 4;
|
||||
|
||||
if (compressedSize <= 0) {
|
||||
// No content to decompress
|
||||
FF_DEBUG("Compressed content size is 0, skipping decompression");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if content is actually in gzip format (gzip header magic is 0x1f 0x8b)
|
||||
if (compressedSize < 2 || (uint8_t)bodyStart[0] != 0x1f || (uint8_t)bodyStart[1] != 0x8b) {
|
||||
FF_DEBUG("Content is not valid gzip format, skipping decompression");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Predict uncompressed size
|
||||
uint32_t estimatedSize = guessGzipOutputSize(bodyStart, compressedSize);
|
||||
|
||||
// Create decompression buffer with estimated size
|
||||
FF_STRBUF_AUTO_DESTROY decompressedBuffer = ffStrbufCreateA(estimatedSize > 0 ? estimatedSize : compressedSize * 5);
|
||||
FF_DEBUG("Created decompression buffer: %u bytes", decompressedBuffer.allocated);
|
||||
|
||||
// Initialize decompression
|
||||
z_stream zs = {
|
||||
.zalloc = Z_NULL,
|
||||
.zfree = Z_NULL,
|
||||
.opaque = Z_NULL,
|
||||
.avail_in = (uInt)compressedSize,
|
||||
.next_in = (Bytef*)bodyStart,
|
||||
.avail_out = (uInt)ffStrbufGetFree(&decompressedBuffer),
|
||||
.next_out = (Bytef*)decompressedBuffer.chars,
|
||||
};
|
||||
|
||||
// Initialize decompression engine
|
||||
if (zlibData.ffinflateInit2_(&zs, 16 + MAX_WBITS, ZLIB_VERSION, (int)sizeof(z_stream)) != Z_OK) {
|
||||
FF_DEBUG("Failed to initialize decompression engine");
|
||||
return false;
|
||||
}
|
||||
uInt availableOut = zs.avail_out;
|
||||
|
||||
// Perform decompression
|
||||
int result = zlibData.ffinflate(&zs, Z_FINISH);
|
||||
|
||||
// If output buffer is insufficient, try to extend buffer
|
||||
while (result == Z_BUF_ERROR || (result != Z_STREAM_END && zs.avail_out == 0))
|
||||
{
|
||||
FF_DEBUG("Output buffer insufficient, trying to extend");
|
||||
|
||||
// Save already decompressed data amount
|
||||
uint32_t alreadyDecompressed = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += alreadyDecompressed;
|
||||
decompressedBuffer.chars[decompressedBuffer.length] = '\0'; // Ensure null-terminated string
|
||||
|
||||
ffStrbufEnsureFree(&decompressedBuffer, decompressedBuffer.length / 2);
|
||||
|
||||
// Set output parameters to point to new buffer
|
||||
zs.avail_out = (uInt)ffStrbufGetFree(&decompressedBuffer);
|
||||
zs.next_out = (Bytef*)(decompressedBuffer.chars + decompressedBuffer.length);
|
||||
availableOut = zs.avail_out;
|
||||
|
||||
// Decompress again
|
||||
result = zlibData.ffinflate(&zs, Z_FINISH);
|
||||
}
|
||||
|
||||
zlibData.ffinflateEnd(&zs);
|
||||
|
||||
// Calculate decompressed size
|
||||
uint32_t decompressedSize = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += decompressedSize;
|
||||
decompressedBuffer.chars[decompressedSize] = '\0'; // Ensure null-terminated string
|
||||
FF_DEBUG("Successfully decompressed %u bytes compressed data to %u bytes", compressedSize, decompressedBuffer.length);
|
||||
|
||||
// Modify Content-Length header and remove Content-Encoding header
|
||||
FF_STRBUF_AUTO_DESTROY newBuffer = ffStrbufCreateA(headerSize + decompressedSize + 64);
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, buffer))
|
||||
{
|
||||
if (ffStrStartsWithIgnCase(line, "Content-Encoding:"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (ffStrStartsWithIgnCase(line, "Content-Length:"))
|
||||
{
|
||||
ffStrbufAppendF(&newBuffer, "Content-Length: %u\r\n", decompressedSize);
|
||||
continue;
|
||||
}
|
||||
else if (line[0] == '\r')
|
||||
{
|
||||
ffStrbufAppendS(&newBuffer, "\r\n");
|
||||
ffStrbufGetlineRestore(&line, &len, buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&newBuffer, line);
|
||||
ffStrbufAppendC(&newBuffer, '\n');
|
||||
}
|
||||
|
||||
ffStrbufAppend(&newBuffer, &decompressedBuffer);
|
||||
ffStrbufDestroy(buffer);
|
||||
ffStrbufInitMove(buffer, &newBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // FF_HAVE_ZLIB
|
||||
@@ -0,0 +1,500 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "common/time.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static const char* tryNonThreadingFastPath(FFNetworkingState* state)
|
||||
{
|
||||
#if defined(TCP_FASTOPEN) || __APPLE__
|
||||
|
||||
if (!state->tfo)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Linux doesn't support sendto() on unconnected sockets
|
||||
FF_DEBUG("TCP Fast Open disabled, skipping");
|
||||
return "TCP Fast Open disabled";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Attempting to use TCP Fast Open to connect");
|
||||
|
||||
#ifndef __APPLE__ // On macOS, TCP_FASTOPEN doesn't seem to be needed
|
||||
// Set TCP Fast Open
|
||||
#ifdef __linux__
|
||||
int flag = 5; // the queue length of pending packets
|
||||
#else
|
||||
int flag = 1; // enable TCP Fast Open
|
||||
#endif
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP,
|
||||
#ifdef __APPLE__
|
||||
// https://github.com/rust-lang/libc/pull/3135
|
||||
0x218 // TCP_FASTOPEN_FORCE_ENABLE
|
||||
#else
|
||||
TCP_FASTOPEN
|
||||
#endif
|
||||
, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_FASTOPEN option: %s", strerror(errno));
|
||||
return "setsockopt(TCP_FASTOPEN) failed";
|
||||
} else {
|
||||
#ifdef __linux__
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option, queue length: %d", flag);
|
||||
#elif defined(__APPLE__)
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN_FORCE_ENABLE option");
|
||||
#else
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
FF_DEBUG("Using sendto() + MSG_DONTWAIT to send %u bytes of data", state->command.length);
|
||||
ssize_t sent = sendto(state->sockfd,
|
||||
state->command.chars,
|
||||
state->command.length,
|
||||
#ifdef MSG_FASTOPEN
|
||||
MSG_FASTOPEN |
|
||||
#endif
|
||||
#ifdef MSG_NOSIGNAL
|
||||
MSG_NOSIGNAL |
|
||||
#endif
|
||||
MSG_DONTWAIT,
|
||||
state->addr->ai_addr,
|
||||
state->addr->ai_addrlen);
|
||||
#else
|
||||
if (fcntl(state->sockfd, F_SETFL, O_NONBLOCK) == -1) {
|
||||
FF_DEBUG("fcntl(F_SETFL) failed: %s", strerror(errno));
|
||||
return "fcntl(F_SETFL) failed";
|
||||
}
|
||||
FF_DEBUG("Using connectx() to send %u bytes of data", state->command.length);
|
||||
// Use connectx to establish connection and send data in one call
|
||||
size_t sent;
|
||||
if (connectx(state->sockfd,
|
||||
&(sa_endpoints_t) {
|
||||
.sae_dstaddr = state->addr->ai_addr,
|
||||
.sae_dstaddrlen = state->addr->ai_addrlen,
|
||||
},
|
||||
SAE_ASSOCID_ANY, state->tfo ? CONNECT_DATA_IDEMPOTENT : 0,
|
||||
&(struct iovec) {
|
||||
.iov_base = state->command.chars,
|
||||
.iov_len = state->command.length,
|
||||
}, 1, &sent, NULL) != 0) sent = 0;
|
||||
if (fcntl(state->sockfd, F_SETFL, 0) == -1) {
|
||||
FF_DEBUG("fcntl(F_SETFL) failed: %s", strerror(errno));
|
||||
return "fcntl(F_SETFL) failed";
|
||||
}
|
||||
#endif
|
||||
if (sent > 0 || (errno == EAGAIN || errno == EWOULDBLOCK
|
||||
#ifdef __APPLE__
|
||||
// On macOS EINPROGRESS means the connection cannot be completed immediately
|
||||
// On Linux, it means the TFO cookie is not available locally
|
||||
|| errno == EINPROGRESS
|
||||
#endif
|
||||
))
|
||||
{
|
||||
FF_DEBUG(
|
||||
#ifdef __APPLE__
|
||||
"connectx()"
|
||||
#else
|
||||
"sendto()"
|
||||
#endif
|
||||
" %s (sent=%zd, errno=%d: %s)", errno == 0 ? "succeeded" : "was in progress",
|
||||
sent, errno, strerror(errno));
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
ffStrbufDestroy(&state->command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_DEBUG(
|
||||
#ifdef __APPLE__
|
||||
"connectx()"
|
||||
#else
|
||||
"sendto()"
|
||||
#endif
|
||||
" failed: %s (errno=%d)", strerror(errno), errno);
|
||||
#ifdef __APPLE__
|
||||
return "connectx() failed";
|
||||
#else
|
||||
return "sendto() failed";
|
||||
#endif
|
||||
#else
|
||||
FF_UNUSED(state);
|
||||
return "TFO support is not available";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Traditional connect and send function
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
const char* ret = NULL;
|
||||
FF_DEBUG("Using traditional connection method to connect");
|
||||
|
||||
FF_DEBUG("Attempting connect() to server...");
|
||||
if(connect(state->sockfd, state->addr->ai_addr, state->addr->ai_addrlen) == -1)
|
||||
{
|
||||
FF_DEBUG("connect() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("connect() succeeded");
|
||||
|
||||
FF_DEBUG("Attempting to send %u bytes of data...", state->command.length);
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
FF_DEBUG("send() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Data sent successfully");
|
||||
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
FF_DEBUG("Error occurred, closing socket");
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
|
||||
exit:
|
||||
FF_DEBUG("Releasing address info and other resources");
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
// Parallel DNS resolution and socket creation
|
||||
static const char* initNetworkingState(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Initializing network connection state: host=%s, path=%s", host, path);
|
||||
|
||||
// Initialize command and host information
|
||||
ffStrbufInitA(&state->command, 64);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
// Add extra optimized HTTP headers
|
||||
ffStrbufAppendS(&state->command, "Connection: close\r\n"); // Explicitly tell the server we don't need to keep the connection
|
||||
|
||||
// If compression needs to be enabled
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Enabling HTTP content compression");
|
||||
ffStrbufAppendS(&state->command, "Accept-Encoding: gzip\r\n");
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&state->command, headers);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
state->thread = 0;
|
||||
FF_DEBUG("Thread ID initialized to 0");
|
||||
#endif
|
||||
|
||||
const char* ret = NULL;
|
||||
|
||||
struct addrinfo hints = {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_NUMERICSERV
|
||||
};
|
||||
|
||||
FF_DEBUG("Resolving address: %s (%s)", host, state->ipv6 ? "IPv6" : "IPv4");
|
||||
// Use AI_NUMERICSERV flag to indicate the service is a numeric port, reducing parsing time
|
||||
|
||||
if(getaddrinfo(host, "80", &hints, &state->addr) != 0)
|
||||
{
|
||||
FF_DEBUG("getaddrinfo() failed: %s", gai_strerror(errno));
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Address resolution successful");
|
||||
|
||||
FF_DEBUG("Creating socket");
|
||||
state->sockfd = socket(state->addr->ai_family, state->addr->ai_socktype, state->addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
FF_DEBUG("socket() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Socket creation successful: fd=%d", state->sockfd);
|
||||
|
||||
int flag = 1;
|
||||
#ifdef TCP_NODELAY
|
||||
// Disable Nagle's algorithm to reduce small packet transmission delay
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_NODELAY: %s", strerror(errno));
|
||||
} else {
|
||||
FF_DEBUG("Successfully disabled Nagle's algorithm");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_QUICKACK
|
||||
// Set TCP_QUICKACK option to avoid delayed acknowledgments
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_QUICKACK, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_QUICKACK: %s", strerror(errno));
|
||||
} else {
|
||||
FF_DEBUG("Successfully enabled TCP quick acknowledgment");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting connection timeout: %u ms", state->timeout);
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
FF_DEBUG("Using TCP_CONNECTIONTIMEOUT: %u seconds", sec);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
FF_DEBUG("Using TCP_KEEPINIT: %u seconds", sec);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
FF_DEBUG("Using TCP_USER_TIMEOUT: %u milliseconds", state->timeout);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#else
|
||||
FF_DEBUG("Current platform does not support TCP connection timeout");
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
FF_DEBUG("Error occurred during initialization");
|
||||
if (state->addr != NULL)
|
||||
{
|
||||
FF_DEBUG("Releasing address information");
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
}
|
||||
|
||||
if (state->sockfd > 0)
|
||||
{
|
||||
FF_DEBUG("Closing socket: fd=%d", state->sockfd);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Preparing to send HTTP request: host=%s, path=%s", host, path);
|
||||
|
||||
if (state->compression)
|
||||
{
|
||||
FF_DEBUG("Compression enabled, checking if zlib is available");
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* zlibError = ffNetworkingLoadZlibLibrary();
|
||||
// Only enable compression if zlib library is successfully loaded
|
||||
if (zlibError == NULL)
|
||||
{
|
||||
FF_DEBUG("Successfully loaded zlib library, compression enabled");
|
||||
} else {
|
||||
FF_DEBUG("Failed to load zlib library, compression disabled: %s", zlibError);
|
||||
state->compression = false;
|
||||
}
|
||||
#else
|
||||
FF_DEBUG("zlib not supported at build time, compression disabled");
|
||||
state->compression = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Compression disabled");
|
||||
}
|
||||
|
||||
const char* initResult = initNetworkingState(state, host, path, headers);
|
||||
if (initResult != NULL) {
|
||||
FF_DEBUG("Initialization failed: %s", initResult);
|
||||
return initResult;
|
||||
}
|
||||
FF_DEBUG("Network state initialization successful");
|
||||
|
||||
const char* tfoResult = tryNonThreadingFastPath(state);
|
||||
if (tfoResult == NULL) {
|
||||
FF_DEBUG("TryNonThreadingFastPath() succeeded or in progress");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("TryNonThreadingFastPath() failed: %s, trying traditional connection", tfoResult);
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
FF_DEBUG("Multithreading mode enabled, creating connection thread");
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
if (state->thread) {
|
||||
FF_DEBUG("Thread creation successful: thread=%p", (void*)state->thread);
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Thread creation failed");
|
||||
} else {
|
||||
FF_DEBUG("Multithreading mode disabled, connecting in main thread");
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (state->thread)
|
||||
{
|
||||
FF_DEBUG("Connection thread is running, waiting for it to complete (timeout=%u ms)", timeout);
|
||||
if (!ffThreadJoin(state->thread, timeout)) {
|
||||
FF_DEBUG("Thread join failed or timed out");
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
FF_DEBUG("Thread completed successfully");
|
||||
state->thread = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
FF_DEBUG("Invalid socket, HTTP request might have failed");
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
}
|
||||
|
||||
// Set larger initial receive buffer instead of small repeated receives
|
||||
int rcvbuf = 65536; // 64KB
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
|
||||
|
||||
#ifdef __APPLE__
|
||||
// poll for the socket to be readable.
|
||||
// Because of the non-blocking connectx() call, the connection might not be established yet
|
||||
FF_DEBUG("Using poll() to check if socket is readable");
|
||||
if (poll(&(struct pollfd) {
|
||||
.fd = state->sockfd,
|
||||
.events = POLLIN
|
||||
}, 1, timeout > 0 ? (int) timeout : -1) == -1)
|
||||
{
|
||||
FF_DEBUG("poll() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
return "poll() failed";
|
||||
}
|
||||
FF_DEBUG("Socket is readable, proceeding to receive data");
|
||||
#else
|
||||
if(timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting receive timeout: %u ms", timeout);
|
||||
struct timeval timev;
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
++recvCount, buffer->length, ffStrbufGetFree(buffer));
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), MSG_WAITALL);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received == 0) {
|
||||
FF_DEBUG("Connection closed (received=0)");
|
||||
} else {
|
||||
FF_DEBUG("Reception failed: %s (errno=%d)", strerror(errno), errno);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = memmem(buffer->chars, buffer->length, "\r\n\r\n", 4);
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
if (clHeader) {
|
||||
contentLength = (uint32_t) strtoul(clHeader + 16, NULL, 10);
|
||||
if (contentLength > 0) {
|
||||
FF_DEBUG("Detected Content-Length: %u, pre-allocating buffer", contentLength);
|
||||
// Ensure buffer is large enough, adding header size and some margin
|
||||
ffStrbufEnsureFree(buffer, contentLength + 16);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0);
|
||||
|
||||
FF_DEBUG("Closing socket: fd=%d", state->sockfd);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
|
||||
if (buffer->length == 0) {
|
||||
FF_DEBUG("Server response is empty");
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
if (contentLength > 0 && buffer->length != contentLength + (uint32_t)(headerEnd - buffer->chars) + 4) {
|
||||
FF_DEBUG("Received content length mismatches: %u != %u", buffer->length, contentLength + (uint32_t)(headerEnd - buffer->chars) + 4);
|
||||
return "Content length mismatch";
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
|
||||
FF_DEBUG("Received valid HTTP 200 response, content %u bytes, total %u bytes", contentLength, buffer->length);
|
||||
} else {
|
||||
FF_DEBUG("Invalid response: %.40s...", buffer->chars);
|
||||
return "Invalid response";
|
||||
}
|
||||
|
||||
// If compression was used, try to decompress
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
FF_DEBUG("Decompression successful or no decompression needed, total length after decompression: %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
//Must be included after <mswsock.h>
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
static LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
static const char* initWsaData(WSADATA* wsaData)
|
||||
{
|
||||
FF_DEBUG("Initializing WinSock");
|
||||
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0) {
|
||||
FF_DEBUG("WSAStartup() failed");
|
||||
return "WSAStartup() failed";
|
||||
}
|
||||
|
||||
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2) {
|
||||
FF_DEBUG("Invalid wsaData version found: %d.%d", LOBYTE(wsaData->wVersion), HIBYTE(wsaData->wVersion));
|
||||
return "Invalid wsaData version found";
|
||||
}
|
||||
|
||||
//Dummy socket needed for WSAIoctl
|
||||
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd == INVALID_SOCKET) {
|
||||
FF_DEBUG("socket(AF_INET, SOCK_STREAM) failed");
|
||||
return "socket(AF_INET, SOCK_STREAM) failed";
|
||||
}
|
||||
|
||||
DWORD dwBytes;
|
||||
GUID guid = WSAID_CONNECTEX;
|
||||
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&guid, sizeof(guid),
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&dwBytes, NULL, NULL) != 0) {
|
||||
FF_DEBUG("WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed");
|
||||
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
|
||||
}
|
||||
|
||||
closesocket(sockfd);
|
||||
FF_DEBUG("WinSock initialized successfully");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Preparing to send HTTP request: host=%s, path=%s", host, path);
|
||||
|
||||
if (state->compression)
|
||||
{
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* zlibError = ffNetworkingLoadZlibLibrary();
|
||||
// Only enable compression if zlib library is successfully loaded
|
||||
if (zlibError == NULL)
|
||||
{
|
||||
FF_DEBUG("Successfully loaded zlib library, compression enabled");
|
||||
} else {
|
||||
FF_DEBUG("Failed to load zlib library, compression disabled: %s", zlibError);
|
||||
state->compression = false;
|
||||
}
|
||||
#else
|
||||
FF_DEBUG("zlib not supported at build time, compression disabled");
|
||||
state->compression = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Compression disabled");
|
||||
}
|
||||
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
FF_DEBUG("WinSock initialization failed: %s", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
{
|
||||
FF_DEBUG("WinSock initialization previously failed");
|
||||
return "initWsaData() failed before";
|
||||
}
|
||||
|
||||
struct addrinfo* addr;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_NUMERICSERV,
|
||||
};
|
||||
|
||||
FF_DEBUG("Resolving address: %s (%s)", host, state->ipv6 ? "IPv6" : "IPv4");
|
||||
if(getaddrinfo(host, "80", &hints, &addr) != 0)
|
||||
{
|
||||
FF_DEBUG("getaddrinfo() failed");
|
||||
return "getaddrinfo() failed";
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
FF_DEBUG("socket() failed");
|
||||
freeaddrinfo(addr);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
DWORD flag = 1;
|
||||
#ifdef TCP_NODELAY
|
||||
// Enable TCP_NODELAY to disable Nagle's algorithm
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_NODELAY: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
} else {
|
||||
FF_DEBUG("Successfully disabled Nagle's algorithm");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set timeout if needed
|
||||
if (state->timeout > 0) {
|
||||
FF_DEBUG("Setting connection timeout: %u ms", state->timeout);
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&state->timeout, sizeof(state->timeout));
|
||||
}
|
||||
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if((state->ipv6
|
||||
? bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = in6addr_any,
|
||||
}, sizeof(struct sockaddr_in6))
|
||||
: bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
}, sizeof(struct sockaddr_in))) != 0)
|
||||
{
|
||||
FF_DEBUG("bind() failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
// Initialize overlapped structure for asynchronous I/O
|
||||
memset(&state->overlapped, 0, sizeof(OVERLAPPED));
|
||||
|
||||
// Build HTTP command
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&command, "Connection: close\r\n"); // Explicitly request connection closure
|
||||
|
||||
// Add compression support if enabled
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Enabling HTTP content compression");
|
||||
ffStrbufAppendS(&command, "Accept-Encoding: gzip\r\n");
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&command, headers);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
|
||||
#ifdef TCP_FASTOPEN
|
||||
if (state->tfo)
|
||||
{
|
||||
// Set TCP Fast Open
|
||||
flag = 1;
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_FASTOPEN option: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
} else {
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("TCP Fast Open disabled");
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Using ConnectEx to send %u bytes of data", command.length);
|
||||
DWORD sent = 0;
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen,
|
||||
command.chars, command.length, &sent, &state->overlapped);
|
||||
|
||||
freeaddrinfo(addr);
|
||||
addr = NULL;
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if (WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
FF_DEBUG("ConnectEx() failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("ConnectEx() pending");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("ConnectEx() succeeded, sent %u bytes of data", (unsigned) sent);
|
||||
}
|
||||
|
||||
// No need to cleanup state fields here since we need them in the receive function
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
FF_DEBUG("Invalid socket, HTTP request might have failed");
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
}
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject with timeout: %u ms", timeout);
|
||||
if (WaitForSingleObject((HANDLE)state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject failed or timed out");
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
FF_DEBUG("WSAGetOverlappedResult failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting receive timeout: %u ms", timeout);
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
// Set larger receive buffer for better performance
|
||||
int rcvbuf = 65536; // 64KB
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&rcvbuf, sizeof(rcvbuf));
|
||||
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
++recvCount, buffer->length, ffStrbufGetFree(buffer));
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received == 0) {
|
||||
FF_DEBUG("Connection closed (received=0)");
|
||||
} else {
|
||||
FF_DEBUG("Reception failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = strstr(buffer->chars, "\r\n\r\n");
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
if (clHeader) {
|
||||
contentLength = (uint32_t) strtoul(clHeader + 16, NULL, 10);
|
||||
if (contentLength > 0) {
|
||||
FF_DEBUG("Detected Content-Length: %u, pre-allocating buffer", contentLength);
|
||||
// Ensure buffer is large enough, adding header size and some margin
|
||||
ffStrbufEnsureFree(buffer, contentLength + 16);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->allocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0);
|
||||
|
||||
FF_DEBUG("Closing socket: fd=%u", (unsigned)state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
|
||||
if (buffer->length == 0) {
|
||||
FF_DEBUG("Server response is empty");
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
|
||||
FF_DEBUG("Received valid HTTP 200 response, content length: %u bytes, total length: %u bytes",
|
||||
contentLength, buffer->length);
|
||||
} else {
|
||||
FF_DEBUG("Invalid response: %.40s...", buffer->chars);
|
||||
return "Invalid response";
|
||||
}
|
||||
|
||||
// If compression was used, try to decompress
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
FF_DEBUG("Decompression successful or no decompression needed, total length after decompression: %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
const char* ret = NULL;
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(state->host.chars, "80", &(struct addrinfo) {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
{
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||
{
|
||||
close(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr);
|
||||
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
close(state->sockfd);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
state->sockfd = -1;
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&state->host);
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
ffStrbufInitS(&state->host, host);
|
||||
|
||||
ffStrbufInitA(&state->command, 64);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
ffStrbufAppendS(&state->command, headers);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
return state->thread ? NULL : "ffThreadCreate(connectAndSend) failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
if (!ffThreadJoin(state->thread, timeout))
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
struct timeval timev;
|
||||
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));
|
||||
}
|
||||
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
close(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
//Must be included after <mswsock.h>
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking.h"
|
||||
|
||||
static LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
static const char* initWsaData(WSADATA* wsaData)
|
||||
{
|
||||
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0)
|
||||
return "WSAStartup() failed";
|
||||
|
||||
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2)
|
||||
return "Invalid wsaData version found";
|
||||
|
||||
//Dummy socket needed for WSAIoctl
|
||||
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd == INVALID_SOCKET)
|
||||
return "socket(AF_INET, SOCK_STREAM) failed";
|
||||
|
||||
DWORD dwBytes;
|
||||
GUID guid = WSAID_CONNECTEX;
|
||||
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&guid, sizeof(guid),
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&dwBytes, NULL, NULL) != 0)
|
||||
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
|
||||
|
||||
closesocket(sockfd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
return "initWsaData() failed before";
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(host, "80", &(struct addrinfo) {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
return "getaddrinfo() failed";
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if((state->ipv6
|
||||
? bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = in6addr_any,
|
||||
}, sizeof(struct sockaddr_in6))
|
||||
: bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
}, sizeof(struct sockaddr_in))) != 0)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&command, headers);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
|
||||
freeaddrinfo(addr);
|
||||
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
if (WaitForSingleObject((HANDLE) state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int) ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length = recvStart + (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
closesocket(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
@@ -28,13 +28,16 @@
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
#endif
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
static inline int ffPipe2(int *fds, int flags)
|
||||
static inline int ffPipe2(int* fds, int flags)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
#ifndef FF_HAVE_PIPE2
|
||||
if(pipe(fds) == -1)
|
||||
return -1;
|
||||
fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | flags);
|
||||
@@ -301,10 +304,30 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (proc)
|
||||
{
|
||||
char** argv = kvm_getargv(kd, proc, 0);
|
||||
if (argv) ffStrbufSetS(exe, argv[0]);
|
||||
if (argv)
|
||||
{
|
||||
const char* arg0 = argv[0];
|
||||
if (arg0[0] == '-') arg0++;
|
||||
ffStrbufSetS(exe, arg0);
|
||||
}
|
||||
}
|
||||
kvm_close(kd);
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
image_info info;
|
||||
int32 cookie = 0;
|
||||
|
||||
while (get_next_image_info(pid, &cookie, &info) == B_OK)
|
||||
{
|
||||
if (info.type != B_APP_IMAGE) continue;
|
||||
ffStrbufSetS(exe, info.name);
|
||||
|
||||
if (exePath)
|
||||
ffStrbufSet(exePath, exe);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(exe->length == 0)
|
||||
@@ -471,6 +494,18 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
|
||||
if (!proc)
|
||||
return "kvm_getprocs() failed";
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
team_info info;
|
||||
if (get_team_info(pid, &info) == B_OK)
|
||||
{
|
||||
ffStrbufSetS(name, info.name);
|
||||
if (ppid)
|
||||
*ppid = info.parent;
|
||||
}
|
||||
|
||||
FF_UNUSED(tty);
|
||||
|
||||
#else
|
||||
|
||||
return "Unsupported platform";
|
||||
|
||||
@@ -39,6 +39,7 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig confi
|
||||
|
||||
switch (options->tempUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_DEFAULT:
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius);
|
||||
break;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <synchapi.h>
|
||||
#include <profileapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
static inline double ffTimeGetTick(void) //In msec
|
||||
@@ -17,6 +19,8 @@ static inline double ffTimeGetTick(void) //In msec
|
||||
LARGE_INTEGER start;
|
||||
QueryPerformanceCounter(&start);
|
||||
return (double) start.QuadPart * 1000 / (double) frequency.QuadPart;
|
||||
#elif defined(__HAIKU__)
|
||||
return (double) system_time() / 1000.;
|
||||
#else
|
||||
struct timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC, &timeNow);
|
||||
@@ -30,6 +34,8 @@ static inline uint64_t ffTimeGetNow(void)
|
||||
uint64_t timeNow;
|
||||
GetSystemTimeAsFileTime((FILETIME*) &timeNow);
|
||||
return (timeNow - 116444736000000000ull) / 10000ull;
|
||||
#elif defined(__HAIKU__)
|
||||
return (uint64_t) real_time_clock_usecs() / 1000u;
|
||||
#else
|
||||
struct timespec timeNow;
|
||||
clock_gettime(CLOCK_REALTIME, &timeNow);
|
||||
@@ -76,6 +82,18 @@ static inline const char* ffTimeToShortStr(uint64_t msec)
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Not thread-safe
|
||||
static inline const char* ffTimeToTimeStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
|
||||
static char buf[32];
|
||||
strftime(buf, sizeof(buf), "%T", localtime(&tsec));
|
||||
sprintf(buf + __builtin_strlen("00:00:00"), ".%03u", (unsigned) (msec % 1000));
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
+6
-16
@@ -104,16 +104,6 @@
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "escape-bedrock",
|
||||
"desc": "On Bedrock Linux, whether to escape the bedrock jail",
|
||||
"remark": "Linux only",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "wmi-timeout",
|
||||
"desc": "Set the timeout (ms) for WMI queries",
|
||||
@@ -693,8 +683,8 @@
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"IEC": "1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ...",
|
||||
"SI": "1000 Bytes = 1 KB, 1000 KB = 1 MB, ...",
|
||||
"JEDEC": "1024 Bytes = 1 kB, 1024 kB = 1 MB, ..."
|
||||
"SI": "1000 Bytes = 1 kB, 1000 kB = 1 MB, ...",
|
||||
"JEDEC": "1024 Bytes = 1 KB, 1024 KB = 1 MB, ..."
|
||||
},
|
||||
"default": "IEC"
|
||||
}
|
||||
@@ -732,11 +722,12 @@
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"D": "Default",
|
||||
"C": "Celsius",
|
||||
"F": "Fahrenheit",
|
||||
"K": "Kelvin"
|
||||
},
|
||||
"default": "C"
|
||||
"default": "D"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1428,10 +1419,9 @@
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"auto": "Auto detection",
|
||||
"auto": "Prefer EGL on *nix; prefer platform specific implementation on others",
|
||||
"egl": "EGL",
|
||||
"glx": "GLX",
|
||||
"osmesa": "OSMesa"
|
||||
"glx": "GLX (*nix only)"
|
||||
},
|
||||
"default": "auto"
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ In 2.24.0 or newer, `{~startIndex,endIndex}` can be specified to slice a string.
|
||||
If an index is omitted, 0 is used. For example, both `{~,0}` `{~0,}` and `{~,}` are same as `{~0,0}` and will always generate a empty string.
|
||||
If `,endIndex` is omitted or greater than the length of the string, the length of string is used.
|
||||
|
||||
In 2.36.0 or newer, `{$NUM}` can be specified to reference a constant defined in `display.constants`. `{$ENV_VAR}` can be specified to reference an environment variable.
|
||||
|
||||
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
|
||||
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
|
||||
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again.
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <private/device/power_managment.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* parseBattery(int dfd, const char* battId, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = openat(dfd, battId, O_RDWR);
|
||||
if (fd < 0) return "openat() failed";
|
||||
|
||||
acpi_battery_info basic = {};
|
||||
if (ioctl(fd, GET_BATTERY_INFO, &basic, sizeof(basic)) != 0)
|
||||
return "ioctl(GET_BATTERY_INFO) failed";
|
||||
acpi_extended_battery_info extended = {};
|
||||
if (ioctl(fd, GET_EXTENDED_BATTERY_INFO, &extended, sizeof(extended)) != 0)
|
||||
return "ioctl(GET_EXTENDED_BATTERY_INFO) failed";
|
||||
|
||||
if (extended.last_full_charge == (uint32)-1)
|
||||
return "Skipped";
|
||||
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInitS(&battery->modelName, extended.model_number);
|
||||
ffStrbufInitS(&battery->manufacturer, extended.oem_info);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
ffStrbufInitS(&battery->technology, extended.type); // extended.technology?
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInitS(&battery->serial, extended.serial_number);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = extended.cycles;
|
||||
battery->timeRemaining = -1;
|
||||
battery->capacity = (double) basic.capacity * 100. / (double) extended.last_full_charge;
|
||||
|
||||
if (basic.state & BATTERY_DISCHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (basic.state & BATTERY_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if (basic.state & BATTERY_CRITICAL_STATE)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
if (basic.state & BATTERY_NOT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/power/acpi_battery/");
|
||||
if (!dir) return "opendir(/dev/power/acpi_battery) failed";
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
parseBattery(dirfd(dir), entry->d_name, results);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -89,6 +89,9 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#elif __HAIKU__
|
||||
// Currently SMBIOS detection is supported in legency BIOS only
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
extern "C" {
|
||||
#include "bluetooth.h"
|
||||
#include "common/io/io.h"
|
||||
}
|
||||
|
||||
#include <bluetooth/LocalDevice.h>
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
using namespace Bluetooth;
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
LocalDevice* dev = LocalDevice::GetLocalDevice();
|
||||
if (!dev) return NULL;
|
||||
|
||||
BString devClass;
|
||||
dev->GetDeviceClass().DumpDeviceClass(devClass);
|
||||
|
||||
FFBluetoothResult* device = (FFBluetoothResult*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, dev->GetFriendlyName());
|
||||
ffStrbufInitS(&device->address, bdaddrUtils::ToString(dev->GetBluetoothAddress()).String());
|
||||
ffStrbufInitS(&device->type, devClass.String());
|
||||
device->battery = 0;
|
||||
device->connected = true;
|
||||
|
||||
// TODO: more devices?
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)&buffer[4], result);
|
||||
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) == 6)
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) >= 5)
|
||||
result->secureBoot = buffer[4] == 1;
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -7,6 +7,7 @@ typedef struct FFBrightnessResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
double min, max, current;
|
||||
bool builtin;
|
||||
} FFBrightnessResult;
|
||||
|
||||
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult
|
||||
|
||||
@@ -42,6 +42,7 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
|
||||
brightness->max = 1;
|
||||
brightness->min = 0;
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
brightness->builtin = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +112,7 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
|
||||
brightness->min = 0;
|
||||
brightness->current = current;
|
||||
ffStrbufInit(&brightness->name);
|
||||
brightness->builtin = false;
|
||||
|
||||
uint8_t edid[128] = {};
|
||||
if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, ARRAY_SIZE(edid)) == KERN_SUCCESS)
|
||||
@@ -179,6 +181,7 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
|
||||
brightness->min = 0;
|
||||
brightness->current = current;
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
brightness->builtin = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
brightness->max = BACKLIGHTMAXLEVELS;
|
||||
brightness->min = 0;
|
||||
brightness->current = status.brightness;
|
||||
brightness->builtin = true;
|
||||
|
||||
struct backlight_info info;
|
||||
if(ioctl(blfd, BACKLIGHTGETINFO, &info) == 0)
|
||||
|
||||
@@ -74,6 +74,7 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
brightness->max = ffStrbufToDouble(&buffer);
|
||||
brightness->min = 0;
|
||||
brightness->current = actualBrightness;
|
||||
brightness->builtin = true;
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
|
||||
|
||||
@@ -7,7 +7,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
// https://man.netbsd.org/NetBSD-10.1/acpiout.4#DESCRIPTION
|
||||
char key[] = "hw.acpi.acpiout0.brightness";
|
||||
char* pn = key + strlen("hw.acpi.acpiout");
|
||||
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
*pn = (char) ('0' + i);
|
||||
@@ -20,6 +20,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = value;
|
||||
brightness->builtin = true;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
brightness->max = param.max;
|
||||
brightness->min = param.min;
|
||||
brightness->current = param.curval;
|
||||
brightness->builtin = true;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ static const char* detectWithWmi(FFlist* result)
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = vtValue.get<uint8_t>();
|
||||
brightness->builtin = true;
|
||||
|
||||
ffStrbufInit(&brightness->name);
|
||||
if (FFWmiVariant vtName = record.get(L"InstanceName"))
|
||||
@@ -61,6 +62,7 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
|
||||
brightness->max = max;
|
||||
brightness->min = min;
|
||||
brightness->current = curr;
|
||||
brightness->builtin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,28 @@
|
||||
// warning: 'AVCaptureDeviceTypeExternalUnknown' is deprecated
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#ifdef MAC_OS_VERSION_14_0
|
||||
// To make fastfetch compiled on newer macOS versions runs on older ones
|
||||
AVF_EXPORT __attribute__((weak_import)) AVCaptureDeviceType const AVCaptureDeviceTypeExternal;
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
FF_SUPPRESS_IO(); // #822
|
||||
|
||||
AVCaptureDeviceType deviceType;
|
||||
AVCaptureDeviceType deviceType = NULL;
|
||||
|
||||
#ifdef MAC_OS_VERSION_14_0
|
||||
// Strangely `@available(macOS 14.0, *)` doesn't work here (#1594)
|
||||
if (@available(macOS 14.0, *))
|
||||
{
|
||||
deviceType = AVCaptureDeviceTypeExternal;
|
||||
if (&AVCaptureDeviceTypeExternal)
|
||||
deviceType = AVCaptureDeviceTypeExternal;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (deviceType == NULL)
|
||||
deviceType = AVCaptureDeviceTypeExternalUnknown;
|
||||
}
|
||||
|
||||
AVCaptureDeviceDiscoverySession* session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera, deviceType]
|
||||
mediaType:AVMediaTypeVideo
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "chassis.h"
|
||||
#include "detection/host/host.h"
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* result)
|
||||
{
|
||||
FFHostResult host = {
|
||||
.family = ffStrbufCreate(),
|
||||
.name = ffStrbufCreate(),
|
||||
.version = ffStrbufCreate(),
|
||||
.sku = ffStrbufCreate(),
|
||||
.serial = ffStrbufCreate(),
|
||||
.uuid = ffStrbufCreate(),
|
||||
.vendor = ffStrbufCreate(),
|
||||
};
|
||||
if (ffDetectHost(&host) != NULL)
|
||||
return "Failed to detect host";
|
||||
|
||||
if (ffStrbufStartsWithS(&host.name, "MacBook "))
|
||||
ffStrbufSetStatic(&result->type, "Laptop");
|
||||
else if (ffStrbufStartsWithS(&host.name, "Mac mini "))
|
||||
ffStrbufSetStatic(&result->type, "Mini PC");
|
||||
else if (ffStrbufStartsWithS(&host.name, "iMac "))
|
||||
ffStrbufSetStatic(&result->type, "All-in-One");
|
||||
else
|
||||
ffStrbufSetStatic(&result->type, "Desktop");
|
||||
|
||||
ffStrbufSet(&result->vendor, &host.vendor);
|
||||
|
||||
ffStrbufDestroy(&host.family);
|
||||
ffStrbufDestroy(&host.name);
|
||||
ffStrbufDestroy(&host.version);
|
||||
ffStrbufDestroy(&host.sku);
|
||||
ffStrbufDestroy(&host.serial);
|
||||
ffStrbufDestroy(&host.uuid);
|
||||
ffStrbufDestroy(&host.vendor);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -10,10 +10,14 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
const char* removeStrings[] = {
|
||||
" CPU", " FPU", " APU", " Processor",
|
||||
" Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core",
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core",
|
||||
" with Radeon Graphics"
|
||||
" 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core"
|
||||
};
|
||||
ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings);
|
||||
uint32_t radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " w/ Radeon "); // w/ Radeon 780M Graphics
|
||||
if (radeonGraphics >= cpu->name.length)
|
||||
radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " with Radeon ");
|
||||
if (radeonGraphics < cpu->name.length)
|
||||
ffStrbufSubstrBefore(&cpu->name, radeonGraphics);
|
||||
ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own
|
||||
ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it
|
||||
ffStrbufRemoveDupWhitespaces(&cpu->name);
|
||||
|
||||
@@ -15,6 +15,7 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "cpu.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <private/shared/cpu_type.h>
|
||||
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
system_info sysInfo;
|
||||
if (get_system_info(&sysInfo) != B_OK)
|
||||
return "get_system_info() failed";
|
||||
|
||||
uint32 topoNodeCount = 0;
|
||||
get_cpu_topology_info(NULL, &topoNodeCount);
|
||||
if (topoNodeCount == 0)
|
||||
return "get_cpu_topology_info(NULL) failed";
|
||||
|
||||
FF_AUTO_FREE cpu_topology_node_info* topology = malloc(sizeof(*topology) * topoNodeCount);
|
||||
if (get_cpu_topology_info(topology, &topoNodeCount) != B_OK)
|
||||
return "get_cpu_topology_info(topology) failed";
|
||||
|
||||
enum cpu_platform platform = B_CPU_UNKNOWN;
|
||||
enum cpu_vendor cpuVendor = B_CPU_VENDOR_UNKNOWN;
|
||||
uint32 cpuModel = 0, frequency = 0;
|
||||
uint16_t packages = 0, cores = 0;
|
||||
|
||||
for (uint32 i = 0; i < topoNodeCount; i++)
|
||||
{
|
||||
switch (topology[i].type) {
|
||||
case B_TOPOLOGY_ROOT:
|
||||
platform = topology[i].data.root.platform;
|
||||
break;
|
||||
|
||||
case B_TOPOLOGY_PACKAGE:
|
||||
cpuVendor = topology[i].data.package.vendor;
|
||||
++packages;
|
||||
break;
|
||||
|
||||
case B_TOPOLOGY_CORE:
|
||||
cpuModel = topology[i].data.core.model;
|
||||
uint32_t freq = (uint32_t) (topology[i].data.core.default_frequency / 1000000);
|
||||
frequency = freq > frequency ? freq : frequency;
|
||||
++cores;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const char *model = get_cpu_model_string(platform, cpuVendor, cpuModel);
|
||||
if (model)
|
||||
ffStrbufSetS(&cpu->name, model);
|
||||
else
|
||||
ffStrbufSetF(&cpu->name, "(Unknown %" B_PRIx32 ")", cpuModel);
|
||||
ffStrbufSetS(&cpu->vendor, get_cpu_vendor_string(cpuVendor));
|
||||
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
if (cpu->frequencyBase < frequency) cpu->frequencyBase = frequency;
|
||||
cpu->packages = packages;
|
||||
cpu->coresPhysical = cores;
|
||||
cpu->coresOnline = cpu->coresLogical = (uint16_t) sysInfo.cpu_count;
|
||||
return NULL;
|
||||
}
|
||||
+147
-71
@@ -10,6 +10,8 @@
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define FF_CPUINFO_PATH "/proc/cpuinfo"
|
||||
|
||||
static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
@@ -283,11 +285,7 @@ static const char* parseCpuInfo(
|
||||
while(ffStrbufGetline(&line, &len, cpuinfo))
|
||||
{
|
||||
//Stop after reasonable information is acquired
|
||||
if((*line == '\0' || *line == '\n')
|
||||
#if __arm__ || __aarch64__ || __loongarch__
|
||||
&& cpu->name.length > 0 // #1202 #1204
|
||||
#endif
|
||||
)
|
||||
if((*line == '\0' || *line == '\n') && cpu->name.length > 0)
|
||||
{
|
||||
ffStrbufGetlineRestore(&line, &len, cpuinfo);
|
||||
break;
|
||||
@@ -296,28 +294,37 @@ static const char* parseCpuInfo(
|
||||
(void)(
|
||||
// arm64 doesn't have "model name"; arm32 does have "model name" but its value is not useful.
|
||||
// "Hardware" should always be used in this case
|
||||
#if !(__arm__ || __aarch64__)
|
||||
#if __x86_64__ || __i386__
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) ||
|
||||
(physicalCoresBuffer->length == 0 && ffParsePropLine(line, "cpu cores :", physicalCoresBuffer)) ||
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz :", cpuMHz)) ||
|
||||
#endif
|
||||
|
||||
#if !(__x86_64__ || __i386__ || __arm__ || __aarch64__)
|
||||
(cpuIsa->length == 0 && ffParsePropLine(line, "isa :", cpuIsa)) ||
|
||||
(cpuUarch->length == 0 && ffParsePropLine(line, "uarch :", cpuUarch)) ||
|
||||
#endif
|
||||
|
||||
#if __arm__ || __aarch64__
|
||||
#elif __arm__ || __aarch64__
|
||||
(cpuImplementer->length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
|
||||
#elif __powerpc__ || __powerpc
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "clock :", cpuMHz)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) ||
|
||||
#elif __mips__ || __mips
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) ||
|
||||
#elif __loongarch__
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "Model Name :", &cpu->name)) ||
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "CPU MHz :", cpuMHz)) ||
|
||||
#elif __riscv__ || __riscv
|
||||
(cpuIsa->length == 0 && ffParsePropLine(line, "isa :", cpuIsa)) ||
|
||||
(cpuUarch->length == 0 && ffParsePropLine(line, "uarch :", cpuUarch)) ||
|
||||
#elif __s390x__
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "processor 0:", &cpu->name)) ||
|
||||
(cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) ||
|
||||
(cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz static :", cpuMHz)) || // This one cannot be detected because of early return
|
||||
#else
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "model :", &cpu->name)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "hardware :", &cpu->name)) ||
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "processor :", &cpu->name)) ||
|
||||
#endif
|
||||
#if __powerpc__ || __powerpc
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
|
||||
#endif
|
||||
#if __mips__
|
||||
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || //For MIPS
|
||||
#endif
|
||||
|
||||
false
|
||||
);
|
||||
}
|
||||
@@ -414,6 +421,59 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if __i386__ || __x86_64__
|
||||
|
||||
FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
|
||||
{
|
||||
const char* p = cpuinfo->chars;
|
||||
uint64_t low = 0, high = 0;
|
||||
|
||||
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:"))))
|
||||
{
|
||||
if (!p) break;
|
||||
p += strlen("\nphysical id\t:");
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
|
||||
high |= 1 << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
p = pend;
|
||||
}
|
||||
|
||||
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ);
|
||||
if (!ffReadFileBuffer(FF_CPUINFO_PATH, &cpuinfo) || cpuinfo.length == 0)
|
||||
return "ffReadFileBuffer(\"" FF_CPUINFO_PATH "\") failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate();
|
||||
const char* error = parseCpuInfo(&cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, NULL,NULL, NULL);
|
||||
if (error) return error;
|
||||
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->packages = getPackageCount(&cpuinfo);
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 0); // physical cores in single package
|
||||
if (cpu->coresPhysical == 0)
|
||||
cpu->coresPhysical = cpu->coresLogical;
|
||||
else if (cpu->packages > 1)
|
||||
cpu->coresPhysical *= cpu->packages;
|
||||
|
||||
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa)
|
||||
{
|
||||
// Always use the last part of the ISA string. Ref: #590 #1204
|
||||
@@ -517,18 +577,20 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu)
|
||||
}
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
|
||||
#ifdef __loongarch__
|
||||
FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const char* key)
|
||||
{
|
||||
const char* p = cpuinfo->chars;
|
||||
uint64_t low = 0, high = 0;
|
||||
uint32_t keylen = (uint32_t) strlen(key);
|
||||
|
||||
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:"))))
|
||||
while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), key, keylen)))
|
||||
{
|
||||
if (!p) break;
|
||||
p += strlen("\nphysical id\t:");
|
||||
p += keylen;
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
|
||||
if (__builtin_expect(id > 64, false))
|
||||
high |= 1 << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
@@ -537,69 +599,83 @@ FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
|
||||
|
||||
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ);
|
||||
if (!ffReadFileBuffer("/proc/cpuinfo", &cpuinfo) || cpuinfo.length == 0)
|
||||
return "ffReadFileBuffer(\"/proc/cpuinfo\") failed";
|
||||
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuIsa = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate();
|
||||
|
||||
const char* error = parseCpuInfo(&cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr);
|
||||
if (error) return error;
|
||||
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresPhysical = cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
|
||||
#if __x86_64__ || __i386__
|
||||
cpu->packages = getPackageCount(&cpuinfo);
|
||||
if (cpu->packages > 1)
|
||||
cpu->coresPhysical *= cpu->packages; // https://github.com/hykilpikonna/hyfetch/issues/374#issuecomment-2571578914
|
||||
#endif
|
||||
|
||||
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
#if __ANDROID__
|
||||
detectAndroid(cpu);
|
||||
#elif !(__x86_64__ || __i386__)
|
||||
#else
|
||||
detectSocName(cpu);
|
||||
#endif
|
||||
|
||||
#if __arm__ || __aarch64__
|
||||
uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16);
|
||||
ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer));
|
||||
detectFrequency(cpu, options);
|
||||
|
||||
if (cpu->name.length == 0)
|
||||
detectArmName(&cpuinfo, cpu, cpuImplementer);
|
||||
#elif !(__x86_64__ || __i386__)
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
if(cpuUarch.length > 0)
|
||||
{
|
||||
if(cpu->name.length > 0)
|
||||
ffStrbufAppendC(&cpu->name, ' ');
|
||||
ffStrbufAppend(&cpu->name, &cpuUarch);
|
||||
}
|
||||
FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ);
|
||||
if (!ffReadFileBuffer(FF_CPUINFO_PATH, &cpuinfo) || cpuinfo.length == 0)
|
||||
return "ffReadFileBuffer(\"" FF_CPUINFO_PATH "\") failed";
|
||||
|
||||
if(cpuIsa.length > 0)
|
||||
FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuIsa = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate();
|
||||
|
||||
const char* error = parseCpuInfo(&cpuinfo, cpu, NULL, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr);
|
||||
if (error) return error;
|
||||
|
||||
if (cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
#if __arm__ || __aarch64__
|
||||
uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16);
|
||||
ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer));
|
||||
|
||||
if (cpu->name.length == 0)
|
||||
detectArmName(&cpuinfo, cpu, cpuImplementer);
|
||||
#elif __riscv__ || __riscv
|
||||
if (cpu->name.length == 0)
|
||||
{
|
||||
parseIsa(&cpuIsa);
|
||||
if(cpu->name.length > 0)
|
||||
ffStrbufAppendC(&cpu->name, ' ');
|
||||
ffStrbufAppend(&cpu->name, &cpuIsa);
|
||||
if(cpuUarch.length > 0)
|
||||
{
|
||||
if(cpu->name.length > 0)
|
||||
ffStrbufAppendC(&cpu->name, ' ');
|
||||
ffStrbufAppend(&cpu->name, &cpuUarch);
|
||||
}
|
||||
|
||||
if(cpuIsa.length > 0)
|
||||
{
|
||||
parseIsa(&cpuIsa);
|
||||
if(cpu->name.length > 0)
|
||||
ffStrbufAppendC(&cpu->name, ' ');
|
||||
ffStrbufAppend(&cpu->name, &cpuIsa);
|
||||
}
|
||||
}
|
||||
#elif __loongarch__
|
||||
cpu->packages = getLoongarchPropCount(&cpuinfo, "\npackage\t\t\t:");
|
||||
cpu->coresPhysical = getLoongarchPropCount(&cpuinfo, "\ncore\t\t\t:");
|
||||
if (cpu->packages > 1) cpu->coresPhysical *= cpu->packages;
|
||||
#elif __s390x__
|
||||
if (ffStrbufSubstrAfterFirstS(&cpu->name, "machine = "))
|
||||
ffStrbufPrependS(&cpu->name, "Machine ");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
return detectCPUX86(options, cpu);
|
||||
#else
|
||||
return detectCPUOthers(options, cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -42,10 +42,11 @@ static const char* detectCpuTemp(double* current)
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL)
|
||||
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL)
|
||||
return "sysctlbyname(machdep.cpu_brand) failed";
|
||||
ffStrbufSetS(&cpu->name, "Unknown CPU");
|
||||
}
|
||||
|
||||
if (ffSysctlGetString("machdep.dmi.processor-vendor", &cpu->vendor) == NULL)
|
||||
@@ -58,6 +59,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
ffCPUDetectSpeedByCpuid(cpu);
|
||||
|
||||
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
|
||||
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
|
||||
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "fastfetch.h"
|
||||
#include "detection/cpuusage/cpuusage.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
|
||||
{
|
||||
system_info sysInfo;
|
||||
if (get_system_info(&sysInfo) != B_OK)
|
||||
return "get_system_info() failed";
|
||||
|
||||
FF_AUTO_FREE cpu_info* cpuInfo = malloc(sizeof(*cpuInfo) * sysInfo.cpu_count);
|
||||
if (get_cpu_info(0, sysInfo.cpu_count, cpuInfo) != B_OK)
|
||||
return "get_cpu_info() failed";
|
||||
|
||||
uint64_t uptime = (uint64_t) system_time();
|
||||
|
||||
for (uint32_t i = 0; i < sysInfo.cpu_count; ++i)
|
||||
{
|
||||
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
|
||||
info->inUseAll = (uint64_t) cpuInfo[i].active_time;
|
||||
info->totalAll = uptime;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
for(struct statfs* fs = buf; fs < buf + size; ++fs)
|
||||
{
|
||||
if(__builtin_expect(options->folders.length, 0))
|
||||
if(__builtin_expect(options->folders.length > 0, 0))
|
||||
{
|
||||
if(!ffDiskMatchMountpoint(options, fs->f_mntonname))
|
||||
continue;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "disk.h"
|
||||
#include "util/stringUtils.h"
|
||||
}
|
||||
#include <fs_info.h>
|
||||
#include <Directory.h>
|
||||
#include <Path.h>
|
||||
|
||||
const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
{
|
||||
int32 pos = 0;
|
||||
|
||||
for (dev_t dev; (dev = next_dev(&pos)) >= B_OK;)
|
||||
{
|
||||
fs_info fs;
|
||||
if (fs_stat_dev(dev, &fs) < -1) continue;
|
||||
|
||||
node_ref node(fs.dev, fs.root);
|
||||
BDirectory dir(&node);
|
||||
BPath path(&dir);
|
||||
if (path.InitCheck() != B_OK) continue;
|
||||
|
||||
if (__builtin_expect(options->folders.length, 0))
|
||||
{
|
||||
if (!ffDiskMatchMountpoint(options, path.Path()))
|
||||
continue;
|
||||
}
|
||||
|
||||
FFDisk* disk = (FFDisk*) ffListAdd(disks);
|
||||
|
||||
disk->bytesTotal = (uint64_t)fs.total_blocks * (uint64_t) fs.block_size;
|
||||
disk->bytesFree = (uint64_t)fs.free_blocks * (uint64_t) fs.block_size;
|
||||
disk->bytesAvailable = disk->bytesFree;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk. c
|
||||
|
||||
disk->filesTotal = (uint32_t) fs.total_nodes;
|
||||
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs.free_nodes);
|
||||
|
||||
ffStrbufInitS(&disk->mountFrom, fs.device_name);
|
||||
ffStrbufInitS(&disk->mountpoint, path.Path());
|
||||
ffStrbufInitS(&disk->filesystem, fs.fsh_name);
|
||||
ffStrbufInitS(&disk->name, fs.volume_name);
|
||||
disk->type = FF_DISK_VOLUME_TYPE_NONE;
|
||||
if (!(fs.flags & B_FS_IS_PERSISTENT))
|
||||
disk->type = (FFDiskVolumeType) (disk->type | FF_DISK_VOLUME_TYPE_HIDDEN_BIT);
|
||||
if (fs.flags & B_FS_IS_READONLY)
|
||||
disk->type = (FFDiskVolumeType) (disk->type | FF_DISK_VOLUME_TYPE_READONLY_BIT);
|
||||
if (fs.flags & B_FS_IS_REMOVABLE)
|
||||
disk->type = (FFDiskVolumeType) (disk->type | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT);
|
||||
if (disk->type == FF_DISK_VOLUME_TYPE_NONE) disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
|
||||
disk->createTime = 0;
|
||||
|
||||
time_t crTime;
|
||||
if (dir.GetCreationTime(&crTime) == B_OK)
|
||||
disk->createTime = (uint64_t) crTime * 1000;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
extern "C" {
|
||||
#include "displayserver.h"
|
||||
}
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Screen.h>
|
||||
|
||||
extern "C" void ffConnectDisplayServerImpl(FFDisplayServerResult* ds);
|
||||
|
||||
static void detectDisplays(FFDisplayServerResult* ds)
|
||||
{
|
||||
// We need a valid be_app to query the app_server here.
|
||||
BApplication app("application/x-vnd.fastfetch-cli-fastfetch");
|
||||
BScreen s{}; // default screen is the main one
|
||||
bool main = true;
|
||||
|
||||
do
|
||||
{
|
||||
if (!s.IsValid())
|
||||
continue;
|
||||
|
||||
display_mode mode;
|
||||
if (s.GetMode(&mode) != B_OK)
|
||||
continue;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateA(128);
|
||||
monitor_info monitor;
|
||||
// WARNING: This is experimental new Haiku API
|
||||
status_t err = s.GetMonitorInfo(&monitor);
|
||||
if (err == B_OK)
|
||||
{
|
||||
ffStrbufSetF(&name, "%s %s", monitor.vendor, monitor.name);
|
||||
ffStrbufTrimRightSpace(&name);
|
||||
}
|
||||
|
||||
uint32_t width = (uint32_t) s.Frame().Width() + 1;
|
||||
uint32_t height = (uint32_t) (uint32_t)s.Frame().Height() + 1;
|
||||
double scaleFactor = (double) 1.0;
|
||||
FFDisplayResult* res = ffdsAppendDisplay(ds,
|
||||
width,
|
||||
height,
|
||||
(double)mode.timing.pixel_clock * 1000 / (mode.timing.v_total * mode.timing.h_total),
|
||||
(uint32_t) (width / scaleFactor + .5),
|
||||
(uint32_t) (height / scaleFactor + .5),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&name,
|
||||
FF_DISPLAY_TYPE_UNKNOWN,
|
||||
main,
|
||||
(uint64_t) s.ID().id,
|
||||
0,
|
||||
0,
|
||||
"BScreen"
|
||||
);
|
||||
if (err == B_OK)
|
||||
{
|
||||
res->manufactureWeek = monitor.produced.week;
|
||||
res->manufactureYear = monitor.produced.year;
|
||||
}
|
||||
main = false;
|
||||
} while (s.SetToNext() == B_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
ffStrbufSetStatic(&ds->wmProcessName, "app_server");
|
||||
ffStrbufSetStatic(&ds->wmPrettyName, "Application Server");
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Application Kit");
|
||||
|
||||
detectDisplays(ds);
|
||||
}
|
||||
@@ -189,26 +189,47 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
|
||||
if (display)
|
||||
{
|
||||
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {
|
||||
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 advColorInfo2 = {
|
||||
.header = {
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO,
|
||||
.size = sizeof(advColorInfo),
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2,
|
||||
.size = sizeof(advColorInfo2),
|
||||
.adapterId = path->targetInfo.adapterId,
|
||||
.id = path->targetInfo.id,
|
||||
}
|
||||
};
|
||||
if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS)
|
||||
if (DisplayConfigGetDeviceInfo(&advColorInfo2.header) == ERROR_SUCCESS)
|
||||
{
|
||||
if (advColorInfo.advancedColorEnabled)
|
||||
if (advColorInfo2.highDynamicRangeUserEnabled)
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
|
||||
else if (advColorInfo.advancedColorSupported)
|
||||
else if (advColorInfo2.highDynamicRangeSupported)
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
|
||||
else
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel;
|
||||
display->bitDepth = (uint8_t) advColorInfo2.bitsPerColorChannel;
|
||||
}
|
||||
else
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
|
||||
{
|
||||
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = {
|
||||
.header = {
|
||||
.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO,
|
||||
.size = sizeof(advColorInfo),
|
||||
.adapterId = path->targetInfo.adapterId,
|
||||
.id = path->targetInfo.id,
|
||||
}
|
||||
};
|
||||
if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS)
|
||||
{
|
||||
if (advColorInfo.advancedColorEnabled)
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
|
||||
else if (advColorInfo.advancedColorSupported)
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
|
||||
else
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
|
||||
display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel;
|
||||
}
|
||||
else
|
||||
display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
|
||||
}
|
||||
if (edidLength > 0)
|
||||
ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
|
||||
|
||||
char buf;
|
||||
ffStrbufAppendS(&drmDir, "/enabled");
|
||||
if (!ffReadFileData(drmDir.chars, sizeof(buf), &buf) || buf != 'e') {
|
||||
if (ffReadFileData(drmDir.chars, sizeof(buf), &buf) <= 0 || buf != 'e') {
|
||||
/* read failed or enabled != "enabled" */
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
|
||||
ffStrbufAppendS(&drmDir, "/status");
|
||||
|
||||
@@ -4,9 +4,15 @@
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#define RESOLV_CONF "/system/settings/network/resolv.conf"
|
||||
#else
|
||||
#define RESOLV_CONF "/etc/resolv.conf"
|
||||
#endif
|
||||
|
||||
const char* ffDetectDNS(FFDNSOptions* options, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf", "r");
|
||||
FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT RESOLV_CONF, "r");
|
||||
if (!file)
|
||||
return "fopen (" FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf) failed";
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ typedef struct FFFontResult
|
||||
* Linux / BSD: Qt, GTK2, GTK3, GTK4
|
||||
* MacOS: System, User, System Mono, User Mono
|
||||
* Windows: Caption, Menu, Message, Status
|
||||
* Haiku: Plain, Menu, Bold, Mono
|
||||
* Other: Unset, Unset, Unset, Unset
|
||||
*/
|
||||
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
extern "C" {
|
||||
#include "font.h"
|
||||
}
|
||||
|
||||
#include <Application.h>
|
||||
#include <Font.h>
|
||||
#include <Menu.h>
|
||||
|
||||
extern "C" {
|
||||
const char* ffDetectFontImpl(FFFontResult* result);
|
||||
}
|
||||
|
||||
static void generateString(FFFontResult* font)
|
||||
{
|
||||
const char* types[] = { "Plain", "Menu", "Bold", "Mono" };
|
||||
for(uint32_t i = 0; i < ARRAY_SIZE(types); ++i)
|
||||
{
|
||||
if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i]))
|
||||
{
|
||||
if(i > 0)
|
||||
ffStrbufAppendS(&font->display, "], ");
|
||||
ffStrbufAppendF(&font->display, "%s [%s", font->fonts[i].chars, types[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(&font->display, " / ");
|
||||
ffStrbufAppendS(&font->display, types[i]);
|
||||
}
|
||||
}
|
||||
ffStrbufAppendC(&font->display, ']');
|
||||
}
|
||||
|
||||
const char* ffDetectFontImpl(FFFontResult* result)
|
||||
{
|
||||
struct menu_info menuInfo;
|
||||
const BFont *f;
|
||||
// We need a valid be_app to query the app_server here.
|
||||
BApplication app("application/x-vnd.fastfetch-cli-fastfetch");
|
||||
|
||||
if ((f = be_plain_font) != NULL)
|
||||
{
|
||||
f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style);
|
||||
ffStrbufAppendF(&result->fonts[0], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size());
|
||||
}
|
||||
if (get_menu_info(&menuInfo) == B_OK)
|
||||
{
|
||||
ffStrbufAppendF(&result->fonts[1], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)menuInfo.font_size);
|
||||
}
|
||||
if ((f = be_bold_font) != NULL)
|
||||
{
|
||||
f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style);
|
||||
ffStrbufAppendF(&result->fonts[2], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size());
|
||||
}
|
||||
if ((f = be_fixed_font) != NULL)
|
||||
{
|
||||
f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style);
|
||||
ffStrbufAppendF(&result->fonts[3], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size());
|
||||
}
|
||||
|
||||
generateString(result);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
extern "C" {
|
||||
#include "gamepad.h"
|
||||
}
|
||||
#include <Joystick.h>
|
||||
|
||||
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
|
||||
{
|
||||
BJoystick js;
|
||||
for (int32 i = 0, n = js.CountDevices(); i < n; ++i)
|
||||
{
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
if (js.GetDeviceName(i, name) == B_OK)
|
||||
{
|
||||
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInitS(&device->name, name);
|
||||
device->battery = 0;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -48,6 +48,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
const char* ffGPUGetVendorString(unsigned vendorId);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
|
||||
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_GPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon GPU";
|
||||
}
|
||||
}
|
||||
@@ -114,7 +115,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
|
||||
gpu->coreUsage = 0.0/0.0;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
CFDictionaryRef perfStatistics = NULL;
|
||||
uint64_t vramUsed = 0, vramTotal = 0;
|
||||
if (ffCfDictGetDict(properties, CFSTR("PerformanceStatistics"), &perfStatistics) == NULL)
|
||||
|
||||
@@ -67,6 +67,9 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
|
||||
gpu->type = device.location == MTLDeviceLocationBuiltIn ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
gpu->index = (uint32_t) device.locationNumber;
|
||||
|
||||
if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0)
|
||||
gpu->shared.total = device.recommendedMaxWorkingSetSize;
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
@@ -76,11 +75,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
ffGPUQueryAmdGpuName(pc->pc_device, pc->pc_revid, gpu);
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#ifdef FF_HAVE_PCIACCESS
|
||||
|
||||
#include "common/properties.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
|
||||
@@ -37,17 +36,14 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) dev->domain << 6) | ((uint64_t) dev->bus << 4) | ((uint64_t) dev->dev << 2) | (uint64_t) dev->func;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) dev->device_id, (unsigned) dev->revision);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
ffGPUQueryAmdGpuName(dev->device_id, dev->revision, gpu);
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "gpu.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <private/drivers/poke.h>
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR);
|
||||
if (pokefd < 0) return "open(POKE_DEVICE_FULLNAME) failed";
|
||||
|
||||
pci_info dev;
|
||||
pci_info_args cmd = {
|
||||
.signature = POKE_SIGNATURE,
|
||||
.info = &dev,
|
||||
};
|
||||
|
||||
for (cmd.index = 0; ioctl(pokefd, POKE_GET_NTH_PCI_INFO, &cmd, sizeof(cmd)) == B_OK && cmd.status == B_OK; ++cmd.index)
|
||||
{
|
||||
if (dev.class_base != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
||||
continue;
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev.vendor_id));
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = ((uint64_t) dev.bus << 4) | ((uint64_t) dev.device << 2) | (uint64_t) dev.function;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName(dev.device_id, dev.revision, gpu);
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(dev.class_sub, dev.vendor_id, dev.device_id, gpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
@@ -491,15 +490,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
char* pend;
|
||||
uint64_t revision = strtoul(buffer->chars, &pend, 16);
|
||||
if (pend != buffer->chars)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
||||
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
|
||||
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
|
||||
#else
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
#endif
|
||||
}
|
||||
ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu);
|
||||
}
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ struct FFNvmlData {
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
|
||||
@@ -36,6 +37,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
|
||||
@@ -130,6 +132,15 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
|
||||
result.memory->total = memory.used + memory.free;
|
||||
result.memory->used = memory.used;
|
||||
}
|
||||
else
|
||||
{
|
||||
nvmlMemory_t memory_v1;
|
||||
if (nvmlData.ffnvmlDeviceGetMemoryInfo(device, &memory_v1) == NVML_SUCCESS)
|
||||
{
|
||||
result.memory->total = memory_v1.total;
|
||||
result.memory->used = memory_v1.used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.coreCount)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "gpu.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifdef __FreeBSD__
|
||||
@@ -16,6 +17,9 @@
|
||||
#if FF_HAVE_EMBEDDED_PCIIDS
|
||||
#include "fastfetch_pciids.c.inc"
|
||||
#endif
|
||||
#if FF_HAVE_EMBEDDED_AMDGPUIDS
|
||||
#include "fastfetch_amdgpuids.c.inc"
|
||||
#endif
|
||||
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
@@ -45,6 +49,8 @@ static const FFstrbuf* loadPciIds()
|
||||
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
|
||||
#elif __sun
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
|
||||
#elif __HAIKU__
|
||||
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/system/data/hwdata/pci.ids", &pciids);
|
||||
#endif
|
||||
|
||||
#endif // FF_CUSTOM_PCI_IDS_PATH
|
||||
@@ -189,3 +195,43 @@ void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device,
|
||||
#endif
|
||||
return parsePciIdsFile(loadPciIds(), subclass, vendor, device, gpu);
|
||||
}
|
||||
|
||||
#if FF_HAVE_EMBEDDED_AMDGPUIDS
|
||||
static inline int amdGpuCmp(const uint32_t* key, const FFArmGpuProduct* element)
|
||||
{
|
||||
// Maximum value of *key is 0x00FFFFFF. `(int) *key` should never overflow
|
||||
return (int) *key - (int) element->id;
|
||||
}
|
||||
|
||||
static bool loadAmdGpuIdsInc(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu)
|
||||
{
|
||||
uint32_t key = (deviceId << 8u) | revision;
|
||||
FFArmGpuProduct* product = bsearch(&key, ffAmdGpuProducts, ARRAY_SIZE(ffAmdGpuProducts), sizeof(*ffAmdGpuProducts), (void*) amdGpuCmp);
|
||||
if (product)
|
||||
{
|
||||
ffStrbufSetS(&gpu->name, product->name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void parseAmdGpuIdsFile(uint16_t deviceId, uint8_t revision, FFGPUResult* gpu)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
||||
#ifdef FF_CUSTOM_AMDGPU_IDS_PATH
|
||||
ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name);
|
||||
#else
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu)
|
||||
{
|
||||
#if FF_HAVE_EMBEDDED_AMDGPUIDS
|
||||
bool ok = loadAmdGpuIdsInc(deviceId, revisionId, gpu);
|
||||
if (ok) return;
|
||||
#endif
|
||||
return parseAmdGpuIdsFile(deviceId, revisionId, gpu);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "gpu.h"
|
||||
#include "common/properties.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
|
||||
@@ -65,11 +64,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
char query[32];
|
||||
snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
||||
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
||||
}
|
||||
ffGPUQueryAmdGpuName((uint16_t) deviceId, (uint8_t) revision, gpu);
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,18 @@ typedef struct {
|
||||
// https://github.com/NVIDIA/nvidia-settings/issues/78#issuecomment-1012837988
|
||||
enum { nvmlMemory_v2 = (unsigned int)(sizeof(nvmlMemory_v2_t) | (2 << 24U)) };
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t
|
||||
// Memory allocation information for a device (v1)
|
||||
typedef struct
|
||||
{
|
||||
// Total physical device memory (in bytes)
|
||||
unsigned long long total;
|
||||
// Unallocated device memory (in bytes)
|
||||
unsigned long long free;
|
||||
// Sum of Reserved and Allocated device memory (in bytes)
|
||||
unsigned long long used;
|
||||
} nvmlMemory_t;
|
||||
|
||||
// https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g805c0647be9996589fc5e3f6ff680c64
|
||||
// Clock types
|
||||
typedef enum {
|
||||
@@ -124,6 +136,8 @@ extern nvmlReturn_t nvmlDeviceGetPciInfo_v3(nvmlDevice_t device, nvmlPciInfo_t*
|
||||
extern nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int* temp);
|
||||
// Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. The reserved amount is supported on version 2 only
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t* memory);
|
||||
// Retrieves the amount of used, free, total memory available on the device, in bytes.
|
||||
extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t *memory);
|
||||
// Gets the device's core count
|
||||
extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores);
|
||||
// Retrieves the maximum clock speeds for the device
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "initsystem.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/haiku/version.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectInitSystem(FFInitSystemResult* result)
|
||||
{
|
||||
// Since it runs first, registrar does not know about it,
|
||||
// so we can't query be_roster for it.
|
||||
const char* path = "/boot/system/servers/launch_daemon";
|
||||
if (!ffPathExists(path, FF_PATHTYPE_FILE))
|
||||
return "launch_daemon is not found";
|
||||
|
||||
ffStrbufSetStatic(&result->exe, path);
|
||||
ffStrbufSetStatic(&result->name, "launch_daemon");
|
||||
|
||||
team_info teamInfo;
|
||||
int32 cookie = 0;
|
||||
while (get_next_team_info(&cookie, &teamInfo) == B_OK)
|
||||
{
|
||||
if (ffStrEquals(teamInfo.args, path))
|
||||
{
|
||||
result->pid = (uint32_t) teamInfo.team;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ffGetFileVersion(path, &result->version);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
extern "C" {
|
||||
#include "keyboard.h"
|
||||
}
|
||||
|
||||
#include <interface/Input.h>
|
||||
#include <support/List.h>
|
||||
|
||||
const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */)
|
||||
{
|
||||
BList list;
|
||||
|
||||
if (get_input_devices(&list) != B_OK)
|
||||
return "get_input_devices() failed";
|
||||
|
||||
for (int32 i = 0, n = list.CountItems(); i < n; i++)
|
||||
{
|
||||
BInputDevice *device = (BInputDevice *) list.ItemAt(i);
|
||||
if (device->Type() != B_KEYBOARD_DEVICE || !device->IsRunning())
|
||||
continue;
|
||||
|
||||
FFKeyboardDevice* item = (FFKeyboardDevice*) ffListAdd(devices);
|
||||
ffStrbufInit(&item->serial);
|
||||
ffStrbufInitS(&item->name, device->Name());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -18,23 +18,27 @@
|
||||
#include <linux/if.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_dl.h>
|
||||
#else
|
||||
#include <netpacket/packet.h>
|
||||
#endif
|
||||
#ifdef __sun
|
||||
#if defined(__sun) || defined(__HAIKU__)
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
static const FFLocalIpNIFlag niFlagOptions[] = {
|
||||
{ IFF_UP, "UP" },
|
||||
{ IFF_BROADCAST, "BROADCAST" },
|
||||
#ifdef IFF_DEBUG
|
||||
{ IFF_DEBUG, "DEBUG" },
|
||||
#endif
|
||||
{ IFF_LOOPBACK, "LOOPBACK" },
|
||||
{ IFF_POINTOPOINT, "POINTOPOINT" },
|
||||
#ifdef IFF_RUNNING
|
||||
{ IFF_RUNNING, "RUNNING" },
|
||||
#endif
|
||||
{ IFF_NOARP, "NOARP" },
|
||||
{ IFF_PROMISC, "PROMISC" },
|
||||
{ IFF_ALLMULTI, "ALLMULTI" },
|
||||
@@ -64,6 +68,13 @@ static const FFLocalIpNIFlag niFlagOptions[] = {
|
||||
#endif
|
||||
#ifdef IFF_CANTCONFIG
|
||||
{ IFF_CANTCONFIG, "CANTCONFIG" },
|
||||
#endif
|
||||
#ifdef __HAIKU__
|
||||
{ IFF_AUTOUP, "IAUTOUP" },
|
||||
{ IFF_SIMPLEX, "SIMPLEX" },
|
||||
{ IFF_LINK, "LINK" },
|
||||
{ IFF_AUTO_CONFIGURED, "AUTO_CONFIGURED" },
|
||||
{ IFF_CONFIGURING, "CONFIGURING" },
|
||||
#endif
|
||||
// sentinel
|
||||
{},
|
||||
@@ -128,8 +139,12 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
|
||||
for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
#ifdef IFF_RUNNING
|
||||
if (!(ifa->ifa_flags & IFF_RUNNING))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name);
|
||||
if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRoute)
|
||||
@@ -190,7 +205,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
|
||||
|
||||
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT));
|
||||
}
|
||||
#if __FreeBSD__ || __OpenBSD__ || __APPLE__ || __NetBSD__
|
||||
#if __FreeBSD__ || __OpenBSD__ || __APPLE__ || __NetBSD__ || __HAIKU__
|
||||
else if (ifa->ifa_addr->sa_family == AF_LINK)
|
||||
{
|
||||
if (!(options->showType & FF_LOCALIP_TYPE_MAC_BIT))
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "memory.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
{
|
||||
system_info info;
|
||||
if (get_system_info(&info) != B_OK)
|
||||
return "Error getting system info";
|
||||
|
||||
ram->bytesTotal = B_PAGE_SIZE * info.max_pages;
|
||||
ram->bytesUsed = B_PAGE_SIZE * info.used_pages;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
extern "C" {
|
||||
#include "mouse.h"
|
||||
}
|
||||
|
||||
#include <interface/Input.h>
|
||||
#include <support/List.h>
|
||||
|
||||
const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */)
|
||||
{
|
||||
BList list;
|
||||
|
||||
if (get_input_devices(&list) != B_OK)
|
||||
return "get_input_devices() failed";
|
||||
|
||||
for (int32 i = 0, n = list.CountItems(); i < n; i++)
|
||||
{
|
||||
BInputDevice *device = (BInputDevice *) list.ItemAt(i);
|
||||
if (device->Type() != B_POINTING_DEVICE || !device->IsRunning())
|
||||
continue;
|
||||
|
||||
FFMouseDevice* item = (FFMouseDevice*) ffListAdd(devices);
|
||||
ffStrbufInit(&item->serial);
|
||||
ffStrbufInitS(&item->name, device->Name());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "common/time.h"
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options);
|
||||
|
||||
static FFlist ioCounters1;
|
||||
static uint64_t time1;
|
||||
|
||||
|
||||
@@ -17,3 +17,4 @@ typedef struct FFNetIOResult
|
||||
} FFNetIOResult;
|
||||
|
||||
const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options);
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
extern "C" {
|
||||
#include "netio.h"
|
||||
#include "common/netif/netif.h"
|
||||
}
|
||||
|
||||
#include <NetworkInterface.h>
|
||||
#include <NetworkRoster.h>
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
{
|
||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||
|
||||
BNetworkInterface interface;
|
||||
uint32 cookie = 0;
|
||||
|
||||
uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex();
|
||||
|
||||
while (roster.GetNextInterface(&cookie, interface) == B_OK)
|
||||
{
|
||||
if (!interface.Exists())
|
||||
continue;
|
||||
|
||||
bool defaultRoute = interface.Index() == defaultRouteIfIndex;
|
||||
if (options->defaultRouteOnly && !defaultRoute)
|
||||
continue;
|
||||
|
||||
if (options->namePrefix.length && strncmp(interface.Name(), options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
ifreq_stats stats = {};
|
||||
if (interface.GetStats(stats) != B_OK) continue;
|
||||
|
||||
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
|
||||
*counters = (FFNetIOResult) {
|
||||
.name = ffStrbufCreateS(interface.Name()),
|
||||
.defaultRoute = defaultRoute,
|
||||
.txBytes = stats.send.bytes,
|
||||
.rxBytes = stats.receive.bytes,
|
||||
.txPackets = stats.send.packets,
|
||||
.rxPackets = stats.receive.packets,
|
||||
.rxErrors = stats.receive.errors,
|
||||
.txErrors = stats.send.errors,
|
||||
.rxDrops = stats.receive.dropped,
|
||||
.txDrops = stats.send.dropped
|
||||
};
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <OpenGLKit.h>
|
||||
|
||||
extern "C" {
|
||||
#include "opengl.h"
|
||||
#include "common/io/io.h"
|
||||
#if FF_HAVE_EGL
|
||||
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result);
|
||||
#endif
|
||||
void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglGetString);
|
||||
}
|
||||
|
||||
static const char* oglDetectOpenGL(FFOpenGLResult* result)
|
||||
{
|
||||
BApplication app("application/x-vnd.fastfetch-cli-fastfetch");
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
BGLView glView(BRect(), "ff_ogl_view", B_FOLLOW_NONE, B_WILL_DRAW, BGL_RGB);
|
||||
auto ffglGetString = (decltype(&glGetString)) glView.GetGLProcAddress("glGetString");
|
||||
if (!ffglGetString) return "glView.GetGLProcAddress() failed";
|
||||
ffOpenGLHandleResult(result, ffglGetString);
|
||||
ffStrbufSetStatic(&result->library, "OpenGLKit");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
{
|
||||
if (options->library == FF_OPENGL_LIBRARY_AUTO)
|
||||
return oglDetectOpenGL(result);
|
||||
else if (options->library == FF_OPENGL_LIBRARY_EGL)
|
||||
{
|
||||
#if FF_HAVE_EGL
|
||||
return ffOpenGLDetectByEGL(result);
|
||||
#else
|
||||
return "fastfetch was compiled without egl support";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return "Unsupported OpenGL library";
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
|
||||
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX)
|
||||
#define FF_HAVE_GL 1
|
||||
|
||||
#include "common/library.h"
|
||||
@@ -155,66 +155,6 @@ static const char* detectByGlx(FFOpenGLResult* result)
|
||||
|
||||
#endif //FF_HAVE_GLX
|
||||
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
#if __has_include(<GL/osmesa.h>)
|
||||
#include <GL/osmesa.h>
|
||||
#else
|
||||
#include <mesa/osmesa.h> // for sunos
|
||||
#endif
|
||||
|
||||
typedef struct OSMesaData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(glGetString)
|
||||
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress)
|
||||
FF_LIBRARY_SYMBOL(OSMesaCreateContext)
|
||||
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent)
|
||||
FF_LIBRARY_SYMBOL(OSMesaDestroyContext)
|
||||
|
||||
OSMesaContext context;
|
||||
} OSMesaData;
|
||||
|
||||
static const char* osMesaHandleContext(FFOpenGLResult* result, OSMesaData* data)
|
||||
{
|
||||
unsigned char buffer[FF_OPENGL_BUFFER_WIDTH * FF_OPENGL_BUFFER_HEIGHT * sizeof(uint32_t)]; // 4 bytes per pixel (RGBA)
|
||||
|
||||
if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE)
|
||||
return "OSMesaMakeCurrent returned GL_FALSE";
|
||||
|
||||
ffOpenGLHandleResult(result, data->ffglGetString);
|
||||
ffStrbufSetF(&result->library, "OSMesa %d.%d.%d", OSMESA_MAJOR_VERSION, OSMESA_MINOR_VERSION, OSMESA_PATCH_VERSION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data)
|
||||
{
|
||||
data->ffglGetString = (void*) data->ffOSMesaGetProcAddress("glGetString");
|
||||
if(data->ffglGetString == NULL)
|
||||
return "OSMesaGetProcAddress(glGetString) returned NULL";
|
||||
|
||||
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
|
||||
if(data->context == NULL)
|
||||
return "OSMesaCreateContext returned NULL";
|
||||
|
||||
const char* error = osMesaHandleContext(result, data);
|
||||
data->ffOSMesaDestroyContext(data->context);
|
||||
return error;
|
||||
}
|
||||
|
||||
static const char* detectByOsMesa(FFOpenGLResult* result)
|
||||
{
|
||||
OSMesaData data;
|
||||
|
||||
FF_LIBRARY_LOAD(osmesa, "dlopen osmesa failed", "libOSMesa" FF_LIBRARY_EXTENSION, 8);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaGetProcAddress);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaCreateContext);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaDestroyContext);
|
||||
|
||||
return osMesaHandleData(result, &data);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_OSMESA
|
||||
|
||||
const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
{
|
||||
#if FF_HAVE_GL
|
||||
@@ -238,15 +178,6 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
#endif
|
||||
}
|
||||
|
||||
if(options->library == FF_OPENGL_LIBRARY_OSMESA)
|
||||
{
|
||||
#ifdef FF_HAVE_OSMESA
|
||||
return detectByOsMesa(result);
|
||||
#else
|
||||
return "fastfetch was compiled without osmesa support";
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* error = ""; // not NULL dummy value
|
||||
|
||||
#ifdef FF_HAVE_EGL
|
||||
@@ -259,9 +190,6 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result)
|
||||
error = detectByGlx(result);
|
||||
#endif
|
||||
|
||||
//We don't use osmesa in auto mode here, because it is a software implementation,
|
||||
//that doesn't reflect the opengl supported by the hardware
|
||||
|
||||
return error;
|
||||
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "os.h"
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os)
|
||||
{
|
||||
ffStrbufSetStatic(&os->name, "Haiku");
|
||||
|
||||
ffStrbufSetStatic(&os->id, "haiku");
|
||||
|
||||
image_info image;
|
||||
int32 cookie = 0;
|
||||
while (get_next_image_info(B_SYSTEM_TEAM, &cookie, &image) == B_OK)
|
||||
{
|
||||
int32 ver = image.api_version;
|
||||
if (ver == 0) continue;
|
||||
|
||||
// https://github.com/haiku/haiku/blob/e63683b2fb337d2034059a7e053c170eaf978142/headers/os/BeBuild.h#L36
|
||||
if (ver < B_HAIKU_VERSION_1_ALPHA_1)
|
||||
{
|
||||
switch (ver)
|
||||
{
|
||||
case B_HAIKU_VERSION_BEOS:
|
||||
ffStrbufSetStatic(&os->version, "BEOS");
|
||||
break;
|
||||
case B_HAIKU_VERSION_BONE:
|
||||
ffStrbufSetStatic(&os->version, "BONE");
|
||||
break;
|
||||
case B_HAIKU_VERSION_DANO:
|
||||
ffStrbufSetStatic(&os->version, "DANO");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 relVer = ver / 0x10000;
|
||||
ver %= 0x10000;
|
||||
if (ver == 0)
|
||||
{
|
||||
ffStrbufSetF(&os->version, "R%d", relVer);
|
||||
}
|
||||
else
|
||||
{
|
||||
relVer++;
|
||||
|
||||
bool isPre = !!(ver & 1);
|
||||
if (ver < B_HAIKU_VERSION_1_PRE_BETA_1)
|
||||
{
|
||||
int32 alphaVer = ver / 0x100;
|
||||
if (isPre)
|
||||
ffStrbufSetF(&os->version, "R%dA%d-", relVer, alphaVer + 1);
|
||||
else
|
||||
ffStrbufSetF(&os->version, "R%dA%d", relVer, alphaVer);
|
||||
}
|
||||
else if (ver < 0x00010000 /* B_HAIKU_VERSION_1 */)
|
||||
{
|
||||
int32 betaVer = (ver - B_HAIKU_VERSION_1_ALPHA_4) / 0x100;
|
||||
if (isPre)
|
||||
ffStrbufSetF(&os->version, "R%dB%d-", relVer, betaVer + 1);
|
||||
else
|
||||
ffStrbufSetF(&os->version, "R%dB%d", relVer, betaVer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!os->version.length)
|
||||
{
|
||||
system_info sys;
|
||||
if (get_system_info(&sys) == B_OK)
|
||||
ffStrbufAppendF(&os->version, "R%ldx", sys.kernel_version);
|
||||
}
|
||||
}
|
||||
@@ -41,10 +41,13 @@ static bool parseOsRelease(const char* fileName, FFOSResult* result)
|
||||
// Common logic for detecting Armbian image version
|
||||
FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result)
|
||||
{
|
||||
if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Official Armbian release images
|
||||
// Possible values `PRETTY_NAME` starts with on Armbian:
|
||||
// - `Armbian` for official releases
|
||||
// - `Armbian_community` for community releases
|
||||
// - `Armbian_Security` for images with kali repo added
|
||||
// - `Armbian-unofficial` for an unofficial image built from source, e.g. during development and testing
|
||||
if (ffStrbufStartsWithS(&result->prettyName, "Armbian"))
|
||||
ffStrbufSetS(&result->name, "Armbian");
|
||||
else if (ffStrbufStartsWithS(&result->prettyName, "Armbian-unofficial ")) // Unofficial Armbian image built from source
|
||||
ffStrbufSetS(&result->name, "Armbian (custom build)");
|
||||
else
|
||||
return false;
|
||||
ffStrbufSet(&result->idLike, &result->id);
|
||||
@@ -80,6 +83,11 @@ FF_MAYBE_UNUSED static void getUbuntuFlavour(FFOSResult* result)
|
||||
ffStrbufSetS(&result->versionID, result->prettyName.chars + strlen("Rhino Linux "));
|
||||
return;
|
||||
}
|
||||
else if(ffStrbufStartsWithS(&result->prettyName, "VanillaOS "))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "vanilla");
|
||||
ffStrbufSetS(&result->idLike, "ubuntu");
|
||||
}
|
||||
|
||||
if(ffStrContains(xdgConfigDirs, "kde") || ffStrContains(xdgConfigDirs, "plasma") || ffStrContains(xdgConfigDirs, "kubuntu"))
|
||||
{
|
||||
@@ -258,7 +266,7 @@ static void detectOS(FFOSResult* os)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if(instance.config.general.escapeBedrock && parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os))
|
||||
if(parseOsRelease(FASTFETCH_TARGET_DIR_ROOT "/bedrock" FASTFETCH_TARGET_DIR_ETC "/bedrock-release", os))
|
||||
{
|
||||
if(os->id.length == 0)
|
||||
ffStrbufAppendS(&os->id, "bedrock");
|
||||
|
||||
@@ -100,7 +100,7 @@ uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir)
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
#ifndef __sun
|
||||
#if !defined(__sun) && !defined(__HAIKU__)
|
||||
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
|
||||
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
|
||||
else
|
||||
|
||||
@@ -18,6 +18,8 @@ typedef struct FFPackagesResult
|
||||
uint32_t guixHome;
|
||||
uint32_t guixSystem;
|
||||
uint32_t guixUser;
|
||||
uint32_t hpkgSystem;
|
||||
uint32_t hpkgUser;
|
||||
uint32_t linglong;
|
||||
uint32_t lpkg;
|
||||
uint32_t lpkgbuild;
|
||||
@@ -30,6 +32,7 @@ typedef struct FFPackagesResult
|
||||
uint32_t pacman;
|
||||
uint32_t pacstall;
|
||||
uint32_t paludis;
|
||||
uint32_t pisi;
|
||||
uint32_t pkg;
|
||||
uint32_t pkgsrc;
|
||||
uint32_t pkgtool;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "packages.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
// TODO: Use the Package Kit C++ API instead (would account for disabled packages)
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_HPKG_BIT))
|
||||
{
|
||||
result->hpkgSystem = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/system/packages", false);
|
||||
result->hpkgUser = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/boot/home/config/packages", false);
|
||||
}
|
||||
}
|
||||
@@ -573,6 +573,8 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", true);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", false);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_QI_BIT)) packageCounts->qi += getNumStrings(baseDir, "/var/qi/installed_packages.list", "\n", "qi");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PISI_BIT)) packageCounts->pisi += getNumElements(baseDir, "/var/lib/pisi/package", true);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGSRC_BIT)) packageCounts->pkgsrc += getNumElements(baseDir, "/usr/pkg/pkgdb", DT_DIR);
|
||||
}
|
||||
|
||||
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "physicaldisk.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <StorageDefs.h>
|
||||
#include <Drivers.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static const char* detectDisk(FFstrbuf* path, const char* diskType, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY);
|
||||
if (rawfd < 0) return "detectDisk: open(rawfd) failed";
|
||||
|
||||
device_geometry geometry;
|
||||
if (ioctl(rawfd, B_GET_GEOMETRY, &geometry, sizeof(geometry)) < 0)
|
||||
return "ioctl(B_GET_GEOMETRY) failed";
|
||||
|
||||
char name[B_OS_NAME_LENGTH];
|
||||
if (ioctl(rawfd, B_GET_DEVICE_NAME, name, sizeof(name)) != 0)
|
||||
{
|
||||
// ioctl reports `not a tty` for NVME drives for some reason
|
||||
snprintf(name, sizeof(name), "Unknown %s drive", diskType);
|
||||
}
|
||||
|
||||
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&device->name, name);
|
||||
ffStrbufInitCopy(&device->devPath, path);
|
||||
ffStrbufInit(&device->serial);
|
||||
ffStrbufInit(&device->revision);
|
||||
ffStrbufInitS(&device->interconnect, diskType);
|
||||
device->temperature = FF_PHYSICALDISK_TEMP_UNSET;
|
||||
device->type = FF_PHYSICALDISK_TYPE_NONE;
|
||||
device->type |= (geometry.read_only ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE) |
|
||||
(geometry.removable ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED);
|
||||
device->size = (uint64_t) geometry.cylinder_count * geometry.head_count * geometry.sectors_per_track * geometry.bytes_per_sector;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* searchRawDeviceFile(FFstrbuf* path, const char* diskType, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path->chars);
|
||||
if (!dir) return "detectDiskType: opendir() failed";
|
||||
uint32_t baseLen = path->length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)))
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
ffStrbufAppendC(path, '/');
|
||||
ffStrbufAppendS(path, entry->d_name);
|
||||
|
||||
struct stat st;
|
||||
if (stat(path->chars, &st) != 0)
|
||||
{
|
||||
ffStrbufSubstrBefore(path, baseLen);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
searchRawDeviceFile(path, diskType, result);
|
||||
else if (ffStrEquals(entry->d_name, "raw"))
|
||||
detectDisk(path, diskType, result);
|
||||
|
||||
ffStrbufSubstrBefore(path, baseLen);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FF_MAYBE_UNUSED FFPhysicalDiskOptions* options)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/disk");
|
||||
if (!dir) return "opendir(/dev/disk) failed";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&path, "/dev/disk/");
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)))
|
||||
{
|
||||
if (entry->d_name[0] == '.' || ffStrEquals(entry->d_name, "virtual")) continue;
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
searchRawDeviceFile(&path, entry->d_name, result);
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result)
|
||||
{
|
||||
system_info info;
|
||||
if (get_system_info(&info) != B_OK)
|
||||
return "Error getting system info";
|
||||
|
||||
*result = info.used_teams;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "publicip.h"
|
||||
#include "common/networking.h"
|
||||
#include "common/networking/networking.h"
|
||||
|
||||
#define FF_UNITIALIZED ((const char*)(uintptr_t) -1)
|
||||
static FFNetworkingState states[2];
|
||||
@@ -19,7 +19,11 @@ void ffPreparePublicIp(FFPublicIpOptions* options)
|
||||
state->ipv6 = options->ipv6;
|
||||
|
||||
if (options->url.length == 0)
|
||||
{
|
||||
state->compression = true;
|
||||
state->tfo = true;
|
||||
*status = ffNetworkingSendHttpRequest(state, options->ipv6 ? "v6.ipinfo.io" : "ipinfo.io", "/json", NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY host = ffStrbufCreateCopy(&options->url);
|
||||
|
||||
@@ -4,29 +4,54 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectSound(FFlist* devices)
|
||||
{
|
||||
char path[] = "/dev/mixer0";
|
||||
#ifndef __NetBSD__
|
||||
int defaultDev = ffSysctlGetInt("hw.snd.default_unit", -1);
|
||||
|
||||
if (defaultDev == -1)
|
||||
return "sysctl(hw.snd.default_unit) failed";
|
||||
#else
|
||||
int defaultDev;
|
||||
{
|
||||
char mixerp[12];
|
||||
ssize_t plen = readlink("/dev/mixer", mixerp, ARRAY_SIZE(mixerp));
|
||||
if (plen < 6)
|
||||
return "readlink(/dev/mixer) failed";
|
||||
defaultDev = mixerp[plen - 1] - '0';
|
||||
if (defaultDev < 0 || defaultDev > 9)
|
||||
return "Invalid mixer device";
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int idev = 0; idev <= 9; ++idev)
|
||||
char path[] = "/dev/mixer0";
|
||||
|
||||
struct oss_sysinfo info = { .nummixers = 9 };
|
||||
|
||||
for (int idev = 0; idev <= info.nummixers; ++idev)
|
||||
{
|
||||
path[strlen("/dev/mixer")] = (char) ('0' + idev);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
|
||||
if (fd < 0) break;
|
||||
|
||||
if (idev == 0)
|
||||
{
|
||||
if (ioctl(fd, SNDCTL_SYSINFO, &info) != 0)
|
||||
return "ioctl(SNDCTL_SYSINFO) failed";
|
||||
}
|
||||
|
||||
uint32_t devmask = 0;
|
||||
if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0)
|
||||
continue;
|
||||
if (!(devmask & SOUND_MASK_VOLUME))
|
||||
continue;
|
||||
|
||||
#if defined(SOUND_MIXER_MUTE) && (SOUND_MIXER_MUTE != SOUND_MIXER_NONE)
|
||||
#define FF_SOUND_HAVE_MIXER_MUTE 1
|
||||
uint32_t mutemask = 0;
|
||||
ioctl(fd, SOUND_MIXER_READ_MUTE, &mutemask); // doesn't seem to be available on DragonFly
|
||||
ioctl(fd, SOUND_MIXER_READ_MUTE, &mutemask);
|
||||
#endif
|
||||
|
||||
struct oss_card_info ci = { .card = idev };
|
||||
if (ioctl(fd, SNDCTL_CARDINFO, &ci) < 0)
|
||||
@@ -40,10 +65,12 @@ const char* ffDetectSound(FFlist* devices)
|
||||
ffStrbufInitS(&device->identifier, path);
|
||||
ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffStrbufInitStatic(&device->platformApi, "OSS");
|
||||
device->volume = mutemask & SOUND_MASK_VOLUME
|
||||
? 0
|
||||
: ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
|
||||
ffStrbufInitF(&device->platformApi, "%s %s", info.product, info.version);
|
||||
device->volume =
|
||||
#ifdef FF_SOUND_HAVE_MIXER_MUTE
|
||||
mutemask & SOUND_MASK_VOLUME ? 0 :
|
||||
#endif
|
||||
((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2;
|
||||
device->active = true;
|
||||
device->main = defaultDev == idev;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "sound.h"
|
||||
#include "util/stringUtils.h"
|
||||
}
|
||||
#include <MediaAddOn.h>
|
||||
#include <MediaNode.h>
|
||||
#include <MediaRoster.h>
|
||||
#include <ParameterWeb.h>
|
||||
|
||||
const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
|
||||
{
|
||||
BMediaRoster* roster = BMediaRoster::Roster();
|
||||
media_node mediaNode;
|
||||
live_node_info liveInfo;
|
||||
dormant_node_info dormantInfo;
|
||||
|
||||
if (roster->GetAudioOutput(&mediaNode) != B_OK)
|
||||
return NULL;
|
||||
|
||||
FFSoundDevice* device = (FFSoundDevice*)ffListAdd(devices);
|
||||
ffStrbufInit(&device->identifier);
|
||||
if (roster->GetDormantNodeFor(mediaNode, &dormantInfo) == B_OK)
|
||||
ffStrbufAppendS(&device->identifier, dormantInfo.name);
|
||||
ffStrbufInit(&device->name);
|
||||
if (roster->GetLiveNodeInfo(mediaNode, &liveInfo) == B_OK)
|
||||
{
|
||||
ffStrbufAppendS(&device->name, liveInfo.name);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
}
|
||||
ffStrbufInitStatic(&device->platformApi, "MediaKit");
|
||||
// We'll check the Mixer actually
|
||||
device->volume = 0;
|
||||
device->active = true;
|
||||
device->main = true;
|
||||
|
||||
roster->ReleaseNode(mediaNode);
|
||||
|
||||
media_node mixer;
|
||||
if (roster->GetAudioMixer(&mixer) != B_OK)
|
||||
return NULL;
|
||||
|
||||
BParameterWeb *web;
|
||||
status_t status = roster->GetParameterWebFor(mixer, &web);
|
||||
roster->ReleaseNode(mixer); // the web is all we need :-)
|
||||
if (status != B_OK)
|
||||
return NULL;
|
||||
|
||||
BContinuousParameter *gain = NULL;
|
||||
BParameter *mute = NULL;
|
||||
BParameter *parameter;
|
||||
for (int32 index = 0; (parameter = web->ParameterAt(index)) != NULL; index++)
|
||||
{
|
||||
// assume the mute preceding master gain control
|
||||
if (ffStrEquals(parameter->Kind(), B_MUTE))
|
||||
mute = parameter;
|
||||
|
||||
if (ffStrEquals(parameter->Kind(), B_MASTER_GAIN))
|
||||
{
|
||||
// Can not use dynamic_cast due to fno-rtti
|
||||
//gain = dynamic_cast<BContinuousParameter *>(parameter);
|
||||
gain = (BContinuousParameter *)(parameter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gain == NULL)
|
||||
return NULL;
|
||||
|
||||
bigtime_t when;
|
||||
size_t size;
|
||||
|
||||
if (mute)
|
||||
{
|
||||
int32 isMute = false;
|
||||
size = sizeof(isMute);
|
||||
if (mute->GetValue(&isMute, &size, &when) == B_OK && isMute)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float volume = 0.0;
|
||||
size = sizeof(volume);
|
||||
if (gain->GetValue(&volume, &size, &when) == B_OK)
|
||||
device->volume = (uint8_t) (100 * (volume - gain->MinValue()) / (gain->MaxValue() - gain->MinValue()));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ static void paSinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, vo
|
||||
ffStrbufInitS(&device->name, i->description);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffStrbufTrimLeft(&device->name, ' ');
|
||||
device->volume = i->mute ? 0 : (uint8_t) (i->volume.values[0] * 100 / PA_VOLUME_NORM);
|
||||
device->volume = i->mute ? 0 : (uint8_t) ((i->volume.values[0] * 100 + PA_VOLUME_NORM / 2 /*round*/) / PA_VOLUME_NORM);
|
||||
device->active = i->active_port && i->active_port->available != PA_PORT_AVAILABLE_NO;
|
||||
device->main = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "sound.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/audioio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
const char* ffDetectSound(FFlist* devices)
|
||||
{
|
||||
int defaultDev;
|
||||
{
|
||||
char audiop[12];
|
||||
ssize_t plen = readlink("/dev/audio", audiop, ARRAY_SIZE(audiop));
|
||||
if (plen < (ssize_t) strlen("audioN"))
|
||||
return "readlink(/dev/audio) failed";
|
||||
defaultDev = audiop[plen - 1] - '0';
|
||||
if (defaultDev < 0 || defaultDev > 9)
|
||||
return "Invalid audio device";
|
||||
}
|
||||
|
||||
char path[] = "/dev/audio0";
|
||||
|
||||
for (int idev = 0; idev < 9; ++idev)
|
||||
{
|
||||
path[strlen("/dev/audio")] = (char) ('0' + idev);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
|
||||
if (fd < 0) break;
|
||||
|
||||
audio_device_t ad;
|
||||
if (ioctl(fd, AUDIO_GETDEV, &ad) < 0)
|
||||
continue;
|
||||
|
||||
audio_info_t ai;
|
||||
if (ioctl(fd, AUDIO_GETINFO, &ai) < 0)
|
||||
continue;
|
||||
|
||||
FFSoundDevice* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->identifier, path);
|
||||
ffStrbufInitS(&device->name, ad.name);
|
||||
ffStrbufTrimRightSpace(&device->name);
|
||||
ffStrbufInitF(&device->platformApi, "%s", "SunAudio");
|
||||
device->volume = (uint8_t) ((ai.play.gain * 100 + AUDIO_MAX_GAIN / 2) / AUDIO_MAX_GAIN);
|
||||
device->active = true;
|
||||
device->main = defaultDev == idev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "sound.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sndio.h>
|
||||
|
||||
static void close_hdl(struct sioctl_hdl** phdl)
|
||||
{
|
||||
assert(phdl);
|
||||
if (*phdl) sioctl_close(*phdl);
|
||||
}
|
||||
|
||||
enum { MAX_CHANNEL_NUM = 8 };
|
||||
|
||||
typedef struct FFSoundDeviceBundle
|
||||
{
|
||||
char name[SIOCTL_DISPLAYMAX];
|
||||
double level[MAX_CHANNEL_NUM];
|
||||
uint8_t iLevel;
|
||||
bool mute[MAX_CHANNEL_NUM];
|
||||
uint8_t iMute;
|
||||
} FFSoundDeviceBundle;
|
||||
|
||||
static void enumerate_props(FFSoundDeviceBundle* bundle, struct sioctl_desc* desc, int val)
|
||||
{
|
||||
if (!desc) return;
|
||||
|
||||
if (desc->type == SIOCTL_SEL)
|
||||
{
|
||||
if (desc->display[0] != '\0' && ffStrEquals(desc->node0.name, "server"))
|
||||
ffStrCopy(bundle->name, desc->display, SIOCTL_DISPLAYMAX);
|
||||
return;
|
||||
}
|
||||
|
||||
if (desc->type != SIOCTL_NUM && desc->type != SIOCTL_SW)
|
||||
return;
|
||||
|
||||
if (!ffStrEquals(desc->node0.name, "output"))
|
||||
return;
|
||||
|
||||
if (ffStrEquals(desc->func, "level"))
|
||||
{
|
||||
if (__builtin_expect(bundle->iLevel == MAX_CHANNEL_NUM, false))
|
||||
return;
|
||||
bundle->level[bundle->iLevel] = (double) val / (double) desc->maxval;
|
||||
++bundle->iLevel;
|
||||
}
|
||||
else if (ffStrEquals(desc->func, "mute"))
|
||||
{
|
||||
if (__builtin_expect(bundle->iMute == MAX_CHANNEL_NUM, false))
|
||||
return;
|
||||
bundle->mute[bundle->iMute] = !!val;
|
||||
++bundle->iMute;
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectSound(FFlist* devices)
|
||||
{
|
||||
__attribute__((__cleanup__(close_hdl))) struct sioctl_hdl* hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
|
||||
if (!hdl) return "sio_open() failed";
|
||||
|
||||
FFSoundDeviceBundle bundle = {};
|
||||
if (sioctl_ondesc(hdl, (void*) enumerate_props, &bundle) == 0)
|
||||
return "sioctl_ondesc() failed";
|
||||
|
||||
if (bundle.iLevel != bundle.iMute || bundle.iLevel == 0)
|
||||
return "Unexpecd sioctl_ondesc() result";
|
||||
|
||||
FFSoundDevice* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, bundle.name);
|
||||
ffStrbufInitS(&device->identifier, SIO_DEVANY);
|
||||
ffStrbufInitStatic(&device->platformApi, "sndio");
|
||||
device->active = true;
|
||||
device->main = true;
|
||||
device->volume = 0;
|
||||
|
||||
double totalLevel = 0;
|
||||
for (uint8_t i = 0; i < bundle.iLevel; ++i)
|
||||
{
|
||||
if (!bundle.mute[i])
|
||||
totalLevel += bundle.level[i];
|
||||
}
|
||||
device->volume = (uint8_t) ((totalLevel * 100 + bundle.iLevel / 2) / bundle.iLevel);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "swap.h"
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
enum { FFMaxNSwap = 8 };
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
{
|
||||
system_info info;
|
||||
if (get_system_info(&info) != B_OK)
|
||||
return "Error getting system info";
|
||||
|
||||
swap->bytesTotal = B_PAGE_SIZE * info.max_swap_pages;
|
||||
swap->bytesUsed = B_PAGE_SIZE * (info.max_swap_pages - info.free_swap_pages);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -418,6 +418,21 @@ static void detectWestonTerminal(FFTerminalFontResult* terminalFont)
|
||||
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
|
||||
}
|
||||
|
||||
#ifdef __HAIKU__
|
||||
static void detectHaikuTerminal(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY font = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY size = ffStrbufCreate();
|
||||
ffParsePropFileConfigValues("Terminal/Default", 2, (FFpropquery[]) {
|
||||
{"\"Half Font Family\" , ", &font},
|
||||
{"\"Half Font Size\" , ", &size},
|
||||
});
|
||||
if (!font.length) ffStrbufSetStatic(&font, "Noto Sans Mono");
|
||||
if (!size.length) ffStrbufSetStatic(&size, "12");
|
||||
ffFontInitValues(&terminalFont->font, font.chars, size.chars);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
if(ffStrbufIgnCaseEqualS(&terminal->processName, "konsole"))
|
||||
@@ -455,5 +470,11 @@ void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFo
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "terminator"))
|
||||
detectTerminator(terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "sakura"))
|
||||
detectFromConfigFile("sakura/sakura.conf", "font=", terminalFont);;
|
||||
detectFromConfigFile("sakura/sakura.conf", "font=", terminalFont);
|
||||
#ifdef __HAIKU__
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "Terminal"))
|
||||
detectHaikuTerminal(terminalFont);
|
||||
#endif
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "termite"))
|
||||
detectFromConfigFile("termite/config", "font =", terminalFont);
|
||||
}
|
||||
|
||||
@@ -20,13 +20,16 @@
|
||||
#include "util/windows/version.h"
|
||||
#include <windows.h>
|
||||
|
||||
static bool getFileVersion(const FFstrbuf* exePath, FFstrbuf* version)
|
||||
static bool getFileVersion(const FFstrbuf* exePath, const wchar_t* stringName, FFstrbuf* version)
|
||||
{
|
||||
wchar_t exePathW[PATH_MAX];
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, exePath->chars, (int)exePath->length, exePathW, ARRAY_SIZE(exePathW));
|
||||
if (len <= 0) return false;
|
||||
return ffGetFileVersion(exePathW, version);
|
||||
return ffGetFileVersion(exePathW, stringName, version);
|
||||
}
|
||||
|
||||
#elif __HAIKU__
|
||||
#include "util/haiku/version.h"
|
||||
#endif
|
||||
|
||||
static bool getExeVersionRaw(FFstrbuf* exe, FFstrbuf* version)
|
||||
@@ -96,7 +99,7 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if(getFileVersion(exe, version))
|
||||
if(getFileVersion(exe, NULL, version))
|
||||
{
|
||||
ffStrbufSubstrBeforeLastC(version, '.');
|
||||
return true;
|
||||
@@ -289,7 +292,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath,
|
||||
if(ffStrEqualsIgnCase(exeName, "powershell") || ffStrEqualsIgnCase(exeName, "powershell_ise"))
|
||||
return getShellVersionWinPowerShell(exe, version);
|
||||
|
||||
return getFileVersion(exe, version);
|
||||
return getFileVersion(exe, NULL, version);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
@@ -669,6 +672,12 @@ FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* e
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (exe->chars[0] == '/')
|
||||
{
|
||||
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
|
||||
if (version->length) return true;
|
||||
}
|
||||
|
||||
if(ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"--version",
|
||||
@@ -699,6 +708,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionSakura(FFstrbuf* exe, FFstrbuf* ve
|
||||
ffStrbufSubstrAfterLastC(version, ' ');
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionTermite(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if(ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) != NULL) // termite v16.9\nvte 0.78.1 +BIDI +GNUTLS +ICU +SYSTEMD
|
||||
return false;
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(version, '\n');
|
||||
ffStrbufSubstrAfterLastC(version, 'v');
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -715,7 +738,7 @@ static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version)
|
||||
return true;
|
||||
}
|
||||
|
||||
return getFileVersion(exe, version);
|
||||
return getFileVersion(exe, NULL, version);
|
||||
}
|
||||
|
||||
static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
|
||||
@@ -725,7 +748,7 @@ static bool getTerminalVersionConEmu(FFstrbuf* exe, FFstrbuf* version)
|
||||
if(version->length)
|
||||
return true;
|
||||
|
||||
return getFileVersion(exe, version);
|
||||
return getFileVersion(exe, NULL, version);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -741,7 +764,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__HAIKU__)
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal"))
|
||||
return getTerminalVersionGnome(exe, version);
|
||||
@@ -804,6 +827,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufIgnCaseEqualS(processName, "sakura"))
|
||||
return getTerminalVersionSakura(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "termite"))
|
||||
return getTerminalVersionTermite(exe, version);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -814,6 +840,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "ConEmu"))
|
||||
return getTerminalVersionConEmu(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "warp.exe"))
|
||||
return getFileVersion(exe, L"ProductVersion", version);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -841,6 +870,11 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "zed"))
|
||||
return getTerminalVersionZed(exe, version);
|
||||
|
||||
#if __HAIKU__
|
||||
if(ffStrbufEqualS(processName, "Terminal"))
|
||||
return ffGetFileVersion(exe->chars, version);
|
||||
#endif
|
||||
|
||||
const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION");
|
||||
if(termProgramVersion)
|
||||
{
|
||||
@@ -884,7 +918,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
return getFileVersion(exe, version);
|
||||
return getFileVersion(exe, NULL, version);
|
||||
|
||||
#else
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user