Compare commits

...

285 Commits

Author SHA1 Message Date
Carter Li 33953a0d18 Merge pull request #583 from fastfetch-cli/dev
Release v2.1.1
2023-10-14 06:08:00 -05:00
李通洲 98e8e599a6 Release v2.1.1 2023-10-14 18:24:58 +08:00
李通洲 5e19838713 Doc: update changelog 2023-10-14 18:19:10 +08:00
李通洲 501803c873 Logo (Builtin): add Xenia
https://github.com/hykilpikonna/hyfetch/issues/197
2023-10-14 18:15:04 +08:00
李通洲 e9c2a43de1 Brightness: add --brightness-ddcci-sleep to set the sleep times (in ms) when sending DDC/CI requests
Fix #580
2023-10-14 10:04:08 +08:00
李通洲 af94596202 Revert "Brightness (Linux): allow specifying busno for ddcutil"
This doesn't seem to improve much performance, but increase code
complexity a lot

This reverts commit 42e87b498c.
2023-10-14 09:35:40 +08:00
李通洲 42e87b498c Brightness (Linux): allow specifying busno for ddcutil
Ref: #580
2023-10-14 01:38:02 +08:00
李通洲 839ff311de Wifi (macOS): work around #581 2023-10-13 16:47:45 +08:00
李通洲 ebab281471 Processes (Linux): fix implementation
`sysinfo.procs` reports number of all running threads, instead of processes
2023-10-11 21:10:47 +08:00
李通洲 582788645d Doc: add information about how to make Termux API actually work 2023-10-11 16:32:20 +08:00
李通洲 643fed7d1c Doc: metion bug #581 2023-10-11 16:31:47 +08:00
李通洲 076324e60e Wifi (macOS): remove undesired code 2023-10-11 15:23:21 +08:00
李通洲 1fe92738d8 macOS: embed Info.plist 2023-10-11 15:17:14 +08:00
李通洲 e319be19de Wifi (macOS): print <unknown ssid> when we can't get SSID
SSID is not available after Sonoma. According to the doc: SSID information is not available unless Location Services is enabled and the user has authorized the calling app to use location services.
2023-10-11 14:48:48 +08:00
李通洲 ab8448ee47 DiskIO (Windows): fix device name detection 2023-10-10 21:51:15 +08:00
李通洲 5493f418ed Users: fix crashing on Windows; rename tty to more common name sessionName 2023-10-10 20:21:11 +08:00
李通洲 4e75fa958d Logo (Builtin): add EndeavourSmall
Ref: https://github.com/dylanaraps/neofetch/pull/2391
2023-10-10 19:21:05 +08:00
李通洲 0847432dd9 CPUUsage: rename cpuusage-display-type to separate 2023-10-10 19:02:42 +08:00
李通洲 e297144fe2 CPUUsage: fix multi core data detection 2023-10-10 18:46:59 +08:00
李通洲 42cf88be9d CPUUsage: support display value per core 2023-10-10 16:24:44 +08:00
李通洲 6b008ed93b CPUUsage (FreeBSD): count cpu cores separately 2023-10-10 13:56:19 +08:00
李通洲 c96d21c7c0 CPUUsage (Linux): count cpu cores separately 2023-10-10 13:41:08 +08:00
李通洲 2feb53149a Revert "CpuUsage (apple): simplify implementation"
This reverts commit cabd36d078.
2023-10-10 13:41:08 +08:00
李通洲 e7df94495c Temp (FreeBSD): improve CPU temp detection 2023-10-10 13:41:08 +08:00
李通洲 42f6d029b0 Doc: update JSON schema; make it more IDE friendly 2023-10-09 20:27:40 +08:00
李通洲 ccbb252466 DiskIO: update doc and json schema 2023-10-09 19:24:25 +08:00
李通洲 d16bdb30b9 DiskIO: update formatting help messages; update json keys 2023-10-09 16:40:47 +08:00
李通洲 8fa6aee571 Disk: move physicalType to module DiskIO
Physical type applies to physical disks, not partitions
2023-10-09 16:32:31 +08:00
李通洲 4194e56912 DiskIO (Windows): better name detection for Github Action 2023-10-09 15:39:34 +08:00
李通洲 a0343d6bf7 CI: run --format json 2023-10-09 14:56:28 +08:00
李通洲 44b417deca DiskIO (FreeBSD): skip /dev/pass* 2023-10-09 14:26:51 +08:00
李通洲 5ccd196ae4 DiskIO: print devPath 2023-10-09 14:24:29 +08:00
李通洲 b76d6e9faa DiskIO (FreeBSD): add support 2023-10-09 14:20:40 +08:00
李通洲 2d2e0ddc6d Libc (FreeBSD): detect FBSD version 2023-10-09 13:28:30 +08:00
李通洲 430da1578d Libc (macOS): detect libSystem version 2023-10-09 10:43:58 +08:00
李通洲 1188db9475 CMake: simplify musl version detection 2023-10-09 10:43:40 +08:00
李通洲 685676bd0f CMake: don't hardcode system arch 2023-10-09 09:05:11 +08:00
李通洲 fa46dce0e1 CMake: detect uclibc and musl version 2023-10-08 21:03:10 +08:00
李通洲 2e60f34cd8 DiskIO: add to presets/all 2023-10-08 21:02:48 +08:00
李通洲 dc50e24a29 Doc: update changelog and readme 2023-10-08 21:02:31 +08:00
Jami Kettunen 1f23e93951 Logo: add Chimera Linux
Ref: https://github.com/chimera-linux/cports/blob/master/contrib/neofetch/patches/chimera.patch
2023-10-08 19:26:11 +08:00
李通洲 8df6409cb1 DiskIO (Windows): better device name detection 2023-10-08 16:46:53 +08:00
李通洲 5c5c66d960 DiskIO: fix segfault... 2023-10-08 16:38:50 +08:00
李通洲 0b0e286b9c DiskIO: support --diskio-name-prefix 2023-10-08 16:30:09 +08:00
李通洲 b2130477ae DiskIO (macOS): add support 2023-10-08 16:29:53 +08:00
李通洲 085d0924db Brightness (Linux): try improving compatibility of ddcutil 2.0
ddcutil 2.0 increases SONAME version to `libddcutil.so.5`. More testing needed

Ref: #576
2023-10-08 10:34:01 +08:00
李通洲 78249bf4f7 CPU: add new option --cpu-freq-ndigits
Fix #578
2023-10-08 10:10:06 +08:00
李通洲 4c9d9f6223 TerminalFont (Linux): fix typo 2023-10-08 09:56:45 +08:00
李通洲 d7649d9f8f DiskIO: fix building 2023-10-08 09:51:51 +08:00
李通洲 49e2acd15e Printing: fix --help *-format 2023-10-08 09:51:51 +08:00
李通洲 e4a6bf17e4 Terminal: support kgx (gnome console)
Fix #577
2023-10-08 09:51:32 +08:00
李通洲 276e22f6b0 DiskIO: init module 2023-10-07 23:56:15 +08:00
李通洲 b1d63e03d8 NetIO: fix --help netio-format 2023-10-07 22:58:50 +08:00
李通洲 55f0f75c95 Packages (Linux): print opkg in JSON format 2023-10-07 17:26:57 +08:00
李通洲 fe4eb564e1 NetIO: add missing #pragma once 2023-10-07 16:12:37 +08:00
李通洲 90ea096ca3 macOS: don't keep variable matchDict 2023-10-07 15:51:05 +08:00
李通洲 3077f885d8 Sound (macOS): ignore input devices 2023-10-07 15:45:14 +08:00
李通洲 41551ef200 Sound: fix typo 2023-10-07 15:15:39 +08:00
李通洲 4c96d0453e TerminalShell (Linux): add ash as a known shell 2023-10-07 15:15:24 +08:00
李通洲 d7ef7bc078 Doc: update changelog 2023-10-07 15:14:16 +08:00
李通洲 c77a758741 Packages (Linux): support opkg
Fix #574
2023-10-07 14:02:16 +08:00
李通洲 12208b2c7c Global: improve support of --help *-format
Also fix some bugs found when refactoring
2023-10-07 13:40:40 +08:00
李通洲 23d2cc3fdc Version: print libc version used when compiling 2023-10-05 22:23:22 +08:00
Md Rasel Hossain 1dfa0315db Fix several --help command related issues (#572)
* Help: fix wrong output for irrelevant commands

* Help: fix `module-format` related issues

* Help: remove unnecessary code
2023-10-05 19:59:24 +08:00
李通洲 f78f97a726 Revert "DisplayServer (Linux): add debug log for #568"
This reverts commit 1a4eb25194.
2023-10-04 16:28:54 +08:00
Carter Li 9972c61bbe Sound (macOS): support non-controllable devices 2023-10-04 14:59:13 +08:00
Carter Li 8795d99f79 Brightness: add DDC/CI support for Intel
Doesn't work for me. Need more testing
2023-10-04 14:41:06 +08:00
Carter Li f8aafb7ce4 Monitor (macOS): better intel platform support 2023-10-04 00:30:35 +08:00
Carter Li 27581d92b5 Disk (macOS): detect physical type 2023-10-04 00:30:35 +08:00
Carter Li 4a89b92185 Disk: allow custiomize disk key with mountFrom 2023-10-04 00:30:35 +08:00
李通洲 1a4eb25194 DisplayServer (Linux): add debug log for #568 2023-10-04 00:30:35 +08:00
李通洲 3eb9acea2e Doc: update changelog 2023-10-03 17:04:08 +08:00
李通洲 be860064c5 Users (Windows): fix crashing caused by uninitialized strings 2023-10-03 17:01:57 +08:00
李通洲 1985552636 Disk (Windows): fix crashing on Windows 7 VM 2023-10-03 16:50:57 +08:00
李通洲 985264d485 Fastfetch: add Directx Headers to --list-features 2023-10-02 23:19:44 +08:00
Carter Li e3c69c4569 Merge pull request #571 from fastfetch-cli/dev
Release v2.1.0
2023-10-02 19:23:07 +08:00
李通洲 45f523adb8 Release v2.1.0 2023-10-02 18:03:10 +08:00
李通洲 f7cc4fb4b1 Doc: update changelog 2023-10-02 18:00:30 +08:00
Alxhr0 ddec13be29 Fix Slackware 2023-10-01 22:37:18 +08:00
李通洲 74ac023cb0 Logo (Builtin): support Oracle Linux Server
Fix #569
2023-10-01 20:52:05 +08:00
李通洲 7f75d42ec8 Logo (Builtin): tidy 2023-10-01 20:50:10 +08:00
李通洲 e53acf42ec Disk (Linux): detect physical type 2023-09-30 20:32:14 +08:00
李通洲 18233a27c5 Disk (Windows): detect disk physical type 2023-09-30 15:00:59 +08:00
李通洲 9857f48bb9 OS (Linux): actually display debian .x version
Also display code name on Linux
2023-09-28 23:40:03 +08:00
李通洲 289976372f Shell: improve nu version detection performance 2023-09-27 20:05:55 +08:00
李通洲 72d2ce4b43 Logo: add LainOS
Ref: https://github.com/dylanaraps/neofetch/pull/2382
2023-09-27 15:52:52 +08:00
李通洲 eb0faec74a NetIO (Android): fix building
Doesn't work because `/sys` is unaccessable on Android
2023-09-27 15:34:53 +08:00
李通洲 767f99cffa CPU (Linux): only try lscpu on Linux
Since `lscpu` is a program of `util-linux`
2023-09-27 15:11:05 +08:00
李通洲 7caa8d4618 CPU (Linux): try detecting CPU name using lscpu
Fix #567
2023-09-27 15:05:26 +08:00
李通洲 88c12486bf Processing (Linux): always set LANG to C before executing child process 2023-09-27 15:02:55 +08:00
李通洲 8b357c27b4 Logo (Builtin): add Amazon LInux
Fix #566
2023-09-27 11:06:09 +08:00
李通洲 a7a8f2f461 NetIO (BSD): fix compiling 2023-09-27 10:48:54 +08:00
李通洲 5e5c0b4a58 NetIO: improve performance 2023-09-27 10:31:35 +08:00
李通洲 154657b455 NetUsage: rename to NetIO 2023-09-27 00:06:11 +08:00
李通洲 3866f27448 NetUsage (BSD): fix compiling 2023-09-26 23:58:05 +08:00
李通洲 b4f29918ed NetUsage: finish docs 2023-09-26 23:18:19 +08:00
李通洲 b29b78b321 NetUsage: finish module 2023-09-26 23:00:31 +08:00
李通洲 917b049030 LocalIP: cache default route value 2023-09-26 21:49:01 +08:00
李通洲 4843dedb4d LocalIp: filter --localip-default-route-only inside detection code 2023-09-26 20:57:02 +08:00
李通洲 69373906ca Windows: pre-basic msvc support 2023-09-26 20:13:32 +08:00
李通洲 24a6efa227 NetUsage: finish first working version 2023-09-26 19:54:19 +08:00
李通洲 9004d9e05c NetUsage (BSD): add detection support 2023-09-26 12:04:19 +08:00
李通洲 fa4fccd426 NetUsage (Windows): add detection support 2023-09-26 11:20:26 +08:00
李通洲 57bd741d96 NetUsage (Linux): new module (WIP) 2023-09-26 11:20:26 +08:00
李通洲 50c8809d51 LocalIp (Linux): add ioCounter detection 2023-09-26 09:52:10 +08:00
李通洲 e4c1ec916b FFstrbuf: change ffStrbufToUInt16 to more general function ffStrbufToUInt 2023-09-26 09:52:10 +08:00
李通洲 a4bc07cba5 LocalIp (Windows): add ioCounter detection 2023-09-26 09:52:10 +08:00
李通洲 40e542852f CMake: disable ASan on macOS
Ref: https://stackoverflow.com/questions/64126942/malloc-nano-zone-abandoned-due-to-inability-to-preallocate-reserved-vm-space
2023-09-26 09:14:39 +08:00
李通洲 bde2d67f25 CMake: disable UBSan 2023-09-26 08:58:16 +08:00
李通洲 6d1bde17c8 Wifi (macOS): silence compiler warnings 2023-09-25 16:11:00 +08:00
李通洲 ad0c2aa2e9 Version: detect compiler and compile time 2023-09-24 23:07:03 +08:00
李通洲 ddbd198864 Doc: update changelog 2023-09-24 22:21:18 +08:00
李通洲 3e768ddfd4 OS (Linux): detect detailed debian version
Ref: https://github.com/dylanaraps/neofetch/issues/2381
2023-09-24 21:50:12 +08:00
李通洲 6ccf8856b9 Bluetooth (Windows): fix mac address detection 2023-09-24 21:16:54 +08:00
李通洲 1caaa69deb Platform: fix memleaks 2023-09-23 11:58:46 +08:00
李通洲 5aa2798e42 Kernel (Windows): detect service pack version 2023-09-23 11:51:37 +08:00
李通洲 597daddf2a Fastfetch: add -c as a shortcut of --load-config 2023-09-23 09:56:34 +08:00
李通洲 ff1c3d9888 Doc: update changelog 2023-09-23 09:56:34 +08:00
李通洲 cc6cdb96fb Networking: support timeout on Linux 2023-09-23 09:56:34 +08:00
李通洲 db5619541a Init (Windows): actually disable stdout buffer with --no-buffer 2023-09-22 15:06:02 +08:00
李通洲 d94fc32f45 Colors: support --colors-key 2023-09-22 15:05:27 +08:00
李通洲 34723bba89 Colors: don't parse --colors-* as --color * 2023-09-22 15:05:27 +08:00
李通洲 a0efbd20a1 Title: make this module formattable 2023-09-22 15:05:27 +08:00
李通洲 4d86c53e81 Custom: code cleanup 2023-09-22 14:57:04 +08:00
李通洲 560c2acb88 Global: add --module-key " " as a magic case for hiding keys 2023-09-21 16:17:23 +08:00
李通洲 592de4c8f2 CI: print dependencies 2023-09-21 16:11:04 +08:00
李通洲 8cbe3f6453 GPU (Linux): add full GPU detection support in WSL
With DX12 API ;)
2023-09-21 15:47:03 +08:00
李通洲 ec8ee1a509 TerminalFont: fix compiler warnings 2023-09-21 15:47:03 +08:00
李通洲 30ae8a2f96 Packages (Linux): fix dpkg package number detection 2023-09-20 16:17:02 +08:00
李通洲 5337e5cead Packages (Linux): fix snap package number detection on systems other than Ubuntu
Fixes 562
2023-09-20 16:03:35 +08:00
李通洲 576fcd7d3d Display: print display type 2023-09-20 16:03:35 +08:00
李通洲 64615e635f Doc: update changelog 2023-09-20 10:16:18 +08:00
李通洲 38c22bf771 Disk (FreeBSD): hide /boot like what linux does 2023-09-20 10:16:18 +08:00
李通洲 064f624eab macOS: fix compiler warnings on latest xcode 2023-09-19 14:43:55 +08:00
李通洲 26e5790a78 Brightness: report more detailed values 2023-09-19 13:25:50 +08:00
李通洲 48cecd0ad1 CPU: update JSON format structure 2023-09-19 10:50:52 +08:00
李通洲 69e57e52ab Disk (Android): fix detection on Android 2023-09-18 23:03:14 +08:00
李通洲 dbd6e45aba Disk (Android): fix build 2023-09-18 22:25:15 +08:00
李通洲 3714dfdca7 Presets: new example 2023-09-18 20:51:09 +08:00
李通洲 06b1051a7e Global: don't trim custom strings
It can be useful to align separators
2023-09-18 20:46:30 +08:00
李通洲 8edb7d3833 Logo: fix Windows 11_small 2023-09-18 20:45:23 +08:00
李通洲 8a14cbae0c JSON: don't print the non-standand NaN 2023-09-18 20:12:33 +08:00
李通洲 7f727086af Disk: move filesystem outside of files (JSON format) 2023-09-18 20:01:41 +08:00
李通洲 7cd79d34bb Presets: remove devinfo and verbose 2023-09-18 14:19:19 +08:00
李通洲 939165d4cf Platform: align logic of getting host name to neofetch
Fixes: #561
2023-09-18 13:56:32 +08:00
李通洲 b4f063e1da Disk (Linux): detect external disk more accurately 2023-09-18 10:06:14 +08:00
李通洲 bdc79a2995 Doc: update changelog 2023-09-18 00:15:15 +08:00
李通洲 2bb78af1a7 Disk (Linux): detect USB devices as external volumes only
Fixes #559
2023-09-18 00:14:05 +08:00
李通洲 d8e4575157 Disk (Linux): fix ZFS subvolume detection 2023-09-17 22:28:03 +08:00
李通洲 b54e182c0f Disk (Windows): detect volume name 2023-09-17 20:41:07 +08:00
李通洲 fe89e71200 Disk (Linux): try fixing zpool detection
Ref: #559
2023-09-17 20:08:46 +08:00
xbt573 fb69d56297 Arguments: handle --lib-pulse properly 2023-09-17 02:13:48 -04:00
李通洲 6c1b39ae60 Shell (FreeBSD): remove trailing \0 2023-09-16 20:46:49 +08:00
李通洲 2082e01555 Theme: support JSON format (2) 2023-09-16 20:36:28 +08:00
李通洲 24a9231ad0 Kernel (Windows): remove trailing \0 2023-09-15 20:58:57 +08:00
李通洲 3c7903cc14 JsonSchema: add processingTimeout 2023-09-15 19:06:32 +08:00
李通洲 b721f9020e Logo (Builtin): improve performance on Windows 2023-09-15 11:07:47 +08:00
李通洲 bd02e5c632 Logo: code refactor 2023-09-15 10:53:09 +08:00
李通洲 0d5cf52f08 FFstrbuf: add ffStrbufAppendNC 2023-09-15 10:35:12 +08:00
李通洲 f97cddf2da JSON: support --stat for flag based configurations 2023-09-14 15:53:44 +08:00
李通洲 49f42cd003 Doc: update changelog 2023-09-14 15:29:15 +08:00
李通洲 0d7dc2d692 Logo (Ubuntu): changed the edges of the Ubuntu logo to make it rounder
Ref: https://github.com/dylanaraps/neofetch/pull/2378
2023-09-14 15:28:33 +08:00
xbt573 2039bed70d Logo (Builtin): add Elbrus 2023-09-14 01:20:40 -04:00
李通洲 9535b6a8bf PublicIP: fix missing new line 2023-09-14 08:55:33 +08:00
李通洲 df945e824b Deps: upgrade yyjson 2023-09-14 08:38:59 +08:00
李通洲 237c6f1c9e Processes / LocalIP: try increasing stability 2023-09-13 23:41:26 +08:00
李通洲 61131073f2 Global: silence compiler warnings 2023-09-13 22:46:11 +08:00
李通洲 013abe2b3e Weather: support JSON format 2023-09-13 18:38:02 +08:00
李通洲 63c29b10fe Weather: code refactor 2023-09-13 18:31:22 +08:00
李通洲 f5ad07a87b PublicIP: support JSON format 2023-09-13 17:56:50 +08:00
李通洲 28d40d9037 Global: fix some memleaks 2023-09-13 17:42:22 +08:00
李通洲 b3bdf494ab PublicIP: code refactor 2023-09-13 17:41:48 +08:00
李通洲 8d914ace33 Doc: update changelog 2023-09-13 17:36:39 +08:00
李通洲 58f234638b Users: make --users-compact false by default 2023-09-13 17:36:39 +08:00
李通洲 7dfc0d8e60 Shell: don't detect user shell 2023-09-13 17:36:39 +08:00
李通洲 2963e3bd93 Terminal: don't print shell information in Terminal module 2023-09-13 17:36:39 +08:00
李通洲 3dfa99c232 WMTheme: support JSON format 2023-09-13 14:25:00 +08:00
李通洲 804463a470 WM: support JSON format 2023-09-13 14:22:04 +08:00
李通洲 77466ba6f5 GPU: tidy 2023-09-13 14:07:14 +08:00
李通洲 3a8819d42b Wifi: support JSON format 2023-09-13 14:01:15 +08:00
李通洲 9765885fe6 Wallpaper: support JSON format 2023-09-13 13:39:56 +08:00
李通洲 16b01a06e0 Vulkan: support JSON format 2023-09-13 09:53:25 +08:00
李通洲 c400261a11 Deps: update yyjson 2023-09-13 09:42:34 +08:00
李通洲 9b72971dc9 Uptime (FreeBSD): fix building 2023-09-13 08:49:10 +08:00
李通洲 4449173b3d Version: support JSON config 2023-09-12 20:36:00 +08:00
李通洲 10a249d3a8 Title: support JSON support 2023-09-12 20:31:19 +08:00
李通洲 e91d011c8c Theme: support JSON format 2023-09-12 20:23:58 +08:00
李通洲 4124c12bac TerminalSize: support JSON format 2023-09-12 16:17:17 +08:00
李通洲 a927f4a04d DateTime: code refactor using ffTimeGetNow 2023-09-12 16:15:57 +08:00
李通洲 f3ec60a061 Uptime: add ffTimeGetNow() and use it 2023-09-12 14:55:33 +08:00
李通洲 2251086c0f TerminalFont: support JSON format 2023-09-12 11:18:05 +08:00
李通洲 9447f1ca80 Terminal: support JSON format 2023-09-12 09:49:36 +08:00
李通洲 f13b771317 Sound: support JSON format 2023-09-12 09:37:24 +08:00
李通洲 257439477e CI: update deps 2023-09-12 09:12:28 +08:00
李通洲 c702865332 Presets: add a new example
Ref: https://github.com/fastfetch-cli/fastfetch/discussions/556
2023-09-11 23:03:03 +08:00
李通洲 e2abe31fc1 Monitor: fix memleaks 2023-09-10 18:39:45 +08:00
李通洲 82c300f7f6 Logo (Builtin): add Afterglow
https://github.com/hykilpikonna/hyfetch/pull/
2023-09-08 21:22:00 +08:00
李通洲 94eb3b89e8 Logo (Builtin): use first color as title color
As what neofetch does
2023-09-08 21:22:00 +08:00
李通洲 f662cc0aa2 Logo (Builtin): update AOSC OS
Ref: https://github.com/hykilpikonna/hyfetch/pull/185
2023-09-08 21:21:33 +08:00
李通洲 1526930e54 Logo (Builtin): update EvolutionOS
Ref: #555
2023-09-08 21:06:37 +08:00
李通洲 1cdc99f327 JSON format: fix some memleaks 2023-09-08 20:25:41 +08:00
李通洲 d97b16950c Shell: JSON format support 2023-09-08 20:02:59 +08:00
李通洲 aff4a57092 Processes: JSON format support 2023-09-08 15:47:37 +08:00
李通洲 826aa2e46d Packages: support JSON format 2023-09-08 15:44:44 +08:00
李通洲 2c59a05dff Users: JSON format support 2023-09-08 15:31:58 +08:00
李通洲 aafd773fe7 Uptime: JSON format support 2023-09-08 15:31:58 +08:00
李通洲 4356974c5b Image: fix separated image printing 2023-09-08 15:31:58 +08:00
李通洲 7f1e2d2f03 Packages (Windows): support winget packages count
Guarded behind `--allow-slow-operations`
2023-09-08 15:25:22 +08:00
李通洲 cde2ba2c18 Uptime: detect boot time 2023-09-08 14:17:34 +08:00
李通洲 a093ca2001 Users: add more detailed information 2023-09-08 10:11:57 +08:00
李通洲 fe9fcd603b CPU (Windows): fix possible memory errors 2023-09-08 10:11:57 +08:00
李通洲 d8b2151143 CPU (macOS): support Apple Silicon frequency detection 2023-09-08 10:11:56 +08:00
李通洲 904c9eb3c4 CPU (macOS): code refactor 2023-09-08 10:11:31 +08:00
李通洲 598dfd2b02 Disk (Apple): use getattrlist to detect volume name
No functional changes
2023-09-08 10:11:29 +08:00
李通洲 77d388ce1d Disk (BSD): use getfsstat instead of getmntinfo for thread safety 2023-09-07 15:47:49 +08:00
李通洲 9eb35d3967 OS: JSON format support 2023-09-07 09:36:04 +08:00
李通洲 34902db21c OpenGL: JSON format support 2023-09-07 09:28:04 +08:00
李通洲 cdaf5e9281 OpenCL: JSON format support 2023-09-07 09:20:52 +08:00
李通洲 98833b4d74 Monitor: add JSON support 2023-09-06 16:33:51 +08:00
李通洲 f995d8d806 PowerAdapter: rename PowerAdapterResult to FFPowerAdapterResult 2023-09-06 16:27:02 +08:00
李通洲 eb4636b947 PowerAdapter: JSON format support 2023-09-06 16:23:57 +08:00
李通洲 a7c6e1165c Swap: JSON format support 2023-09-06 16:01:10 +08:00
李通洲 8bb88d1806 Memory: JSON format support 2023-09-06 15:59:56 +08:00
李通洲 849ff95116 Player: JSON format support 2023-09-06 15:53:52 +08:00
李通洲 dc29271987 Media: add JSON format support 2023-09-06 15:48:39 +08:00
李通洲 623c5d8eb9 LocalIP: add JSON format support 2023-09-05 16:31:54 +08:00
李通洲 e0ce520e0a Locale: add JSON format support 2023-09-05 16:25:08 +08:00
李通洲 f9cd032a5f LM: add JSON format support 2023-09-05 16:22:37 +08:00
李通洲 39b21f95b7 Kernel: add JSON format support 2023-09-05 16:10:28 +08:00
李通洲 dfbfb88a45 Icons: add JSON formatting support 2023-09-05 16:10:28 +08:00
李通洲 971a69ad1b Host: add JSON formatting support 2023-09-05 15:57:18 +08:00
李通洲 fddf6ddf1e CPU: don't use NaN in JSON 2023-09-05 15:51:09 +08:00
李通洲 81c625e7c9 GPU: add JSON printing support 2023-09-05 15:49:22 +08:00
李通洲 97293ddee1 Gamepad: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 21f36b564f Font: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 34e2b0f89c Display: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 d5ca6aa462 Disk: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 639ad436a0 Global: code refactor 2023-09-05 15:29:46 +08:00
李通洲 76fce2c5a9 DE: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 632718e1d0 DateTime: support JSON printing 2023-09-05 15:29:46 +08:00
李通洲 a4fababb71 Cursor: add JSON format support 2023-09-05 15:29:46 +08:00
李通洲 ac8741d57d CPUUsage: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 28e412b79d CPU: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 01aa9b9516 Command: add JSON printing support 2023-09-05 15:29:46 +08:00
李通洲 acd353b8b3 Chassis: add Json printing support 2023-09-05 15:29:46 +08:00
李通洲 c5d8d976f6 Brightness: add Json printing support 2023-09-05 15:29:46 +08:00
李通洲 3d44514b24 Board: support Json printing 2023-09-05 15:29:46 +08:00
李通洲 fb3fb1bf99 Bluetooth: rename FFBluetoothDevice to FFBluetoothResult 2023-09-05 15:29:46 +08:00
李通洲 757e5f8174 Bluetooth: support Json printing 2023-09-05 15:29:46 +08:00
李通洲 3669f2aee4 Battery: rename BatteryResult to FFBatteryResult 2023-09-05 15:29:46 +08:00
李通洲 14f26879de Global: init --format json support (#527) 2023-09-05 15:29:46 +08:00
李通洲 2f46a77ff2 TerminalFont: better kitty font detection 2023-09-04 19:19:55 +08:00
李通洲 10853fdf35 Doc: add note for image protocol support of Android 2023-09-03 22:51:28 +08:00
李通洲 591fd558e1 Logo: fix --logo-padding for --logo-separate 2023-09-03 22:39:09 +08:00
李通洲 b863e65ea3 OpenGL: silence warnings 2023-09-03 22:21:53 +08:00
李通洲 fc61f64630 Logo: add --logo-separate true 2023-09-03 22:20:11 +08:00
李通洲 3483673ef7 Terminal (Android): fix termux detection 2023-09-03 20:57:23 +08:00
李通洲 9e839d3b8b Logo: simplify code 2023-09-03 19:55:57 +08:00
李通洲 33f121d7fb JsonSchema: fix the name of property defaultRouteOnly 2023-09-03 19:01:52 +08:00
李通洲 9500ca8f83 Logo: fix poll() timeout or failed error when image is very large
Fix #554
2023-09-03 17:50:20 +08:00
李通洲 4dfbc0f909 Logo: try fixing #553 2023-09-02 22:32:34 +08:00
李通洲 effb685fba Logo: try improving performance for image-raw 2023-09-02 10:08:08 -04:00
李通洲 3692e49e9b TerminalShell: correctly set PATH_MAX on Linux 2023-09-02 10:05:30 -04:00
李通洲 04d56d9b6a IO: fix short read when reading from pipe 2023-09-02 10:04:57 -04:00
李通洲 34417ae692 TerminalFont: support contour 2023-09-02 08:11:21 -04:00
李通洲 67d04a746e Terminal: support contour version detection 2023-09-02 07:40:23 -04:00
李通洲 552e0f84aa Doc: update changelog 2023-09-02 00:47:05 -04:00
李通洲 3e880fedf7 Logo: support kitty-direct / iterm without specifying logo width / height
Fixes #550
2023-09-02 00:46:39 -04:00
李通洲 e5c4a6ed2c Logo (Builtin): update EvolutionOS
Closes #551
2023-09-01 23:29:23 -04:00
李通洲 0bda7d80c2 Doc: update README for image logo on Windows 2023-08-30 22:21:29 +08:00
李通洲 7cb86df48d Logo: improve performance on Windows for iterm protocol 2023-08-30 22:17:51 +08:00
李通洲 21e5df2826 Global: replace cpu-usage to cpuusage 2023-08-29 17:47:20 +08:00
李通洲 a5ee51e156 Global: use FF_LIST_AUTO_DESTROY 2023-08-29 10:49:22 +08:00
李通洲 bddcb4772c DE (FreeBSD): add fast path for xfce4 version detection 2023-08-29 10:47:24 +08:00
Carter Li a3f13bdca9 Merge pull request #545 from fastfetch-cli/dev
Release v2.0.5
2023-08-26 20:31:27 +08:00
李通洲 55444b9c4e Release v2.0.5 2023-08-26 08:16:06 -04:00
李通洲 2f14d7742e Display (Linux): fix memleaks 2023-08-26 05:52:06 -04:00
李通洲 0534882f4e Cursor: Don't print 0px 2023-08-26 05:43:15 -04:00
李通洲 ce2f2f4416 Doc: update changelog 2023-08-26 05:31:00 -04:00
李通洲 5259aeb039 Display: fix segfault when using libxrandr
Fix #544
2023-08-26 05:28:21 -04:00
李通洲 e51999edd1 Doc: update changelog 2023-08-26 13:43:33 +08:00
李通洲 2f96c847b9 Disk: print Read-only 2023-08-26 13:43:33 +08:00
李通洲 32d6436027 Disk: add --disk-show-readonly 2023-08-26 13:43:33 +08:00
李通洲 7358326a13 Disk: add --disk-use-available
fix #543
2023-08-26 13:43:13 +08:00
李通洲 434a879538 Disk: rename FFDiskType to FFDiskVolumeType 2023-08-26 13:40:40 +08:00
299 changed files with 7816 additions and 2345 deletions
+54 -20
View File
@@ -13,24 +13,29 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-20.04]
compiler: [gcc, clang, "musl-gcc"]
compiler: [
{ cc: gcc, cxx: "g++" },
{ cc: clang, cxx: "clang++" },
{ cc: "musl-gcc", cxx: "musl-g++" }
]
enableFeatures: [ON, OFF]
exclude:
# The feature libraries are all build against glibc, so they can't be used with musl
- compiler: "musl-gcc"
- compiler: { cc: "musl-gcc", cxx: "musl-g++" }
enableFeatures: ON
runs-on: ${{ matrix.os }}
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev
run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
- name: configure project
env:
CC: ${{ matrix.compiler }}
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} .
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} .
- name: build project
run: cmake --build .
@@ -39,10 +44,13 @@ jobs:
run: ctest
- name: run fastfetch
run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: ./flashfetch
run: time ./flashfetch
linux:
name: Linux
@@ -54,10 +62,10 @@ jobs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev
run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
@@ -77,11 +85,17 @@ jobs:
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest
@@ -103,7 +117,7 @@ jobs:
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: install required packages
run: brew install vulkan-loader molten-vk imagemagick chafa
@@ -126,11 +140,17 @@ jobs:
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: otool -L fastfetch
- name: run tests
run: ctest
@@ -148,19 +168,21 @@ jobs:
contents: read
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: run VM
uses: vmactions/freebsd-vm@v0
with:
prepare: |
pkg install -y cmake git pkgconf pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
cmake --build . --target package
./fastfetch --list-features
time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
time ./fastfetch -c presets/ci
time ./fastfetch -c presets/ci --format json
time ./flashfetch
ldd fastfetch
ctest
- name: upload artifacts
@@ -180,7 +202,7 @@ jobs:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: setup-msys2
uses: msys2/setup-msys2@v2
@@ -213,11 +235,17 @@ jobs:
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest
@@ -244,7 +272,7 @@ jobs:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: setup-msys2
uses: msys2/setup-msys2@v2
@@ -274,11 +302,17 @@ jobs:
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
- name: run fastfetch
run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all
run: time ./fastfetch -c presets/ci
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest
+88 -1
View File
@@ -1,7 +1,94 @@
# 2.1.1
Features:
* Support opkg (Packages, Linux)
* Support GNOME Console terminal version and font detection (Terminal, Linux)
* Add `--cpu-freq-ndigits` to set number of digits for CPU frequency (CPU)
* New module to detect physical disk I/O usage (DiskIO)
* Add `--cpuusage-separate` to display CPU usage per CPU logical core
* Add `--brightness-ddcci-sleep` to set the sleep times (in ms) when sending DDC/CI requests (Brightness, #580)
Bugfixes:
* Fix possible crashes on Windows 7 (Disk, Windows)
* Fix possible crashes caused by uninitialized strings (Users, Windows)
* Improve support of `--help *-format` and several bugs are found and fixed
* Don't incorrectly print `No active sound devices found` when using a non-controllable sound device (Sound, macOS)
* Fix implementation processes counting (Processes, Linux)
* Work around a issue that SSID cannot be detected on macOS Sonoma (Wifi, macOS)
Logo:
* Add Chimera Linux
* Add EndeavourSmall
* Add Xenia
# 2.1.0
This release introduces a new output format: JSON result
Changes:
* Users module detects and prints user login time by default. Specifying `--users-compact` to disable it
* Fastfetch now requires yyjson 0.8.0 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package
* Reduced information supported by `--terminal-format`, `--shell-format`
* Some config presets (`devinfo` and `verbose`) are obseleted and removed. They are barely maintained and can be replaced with `--format json` now.
* Custom strings in `--module-key` and `--module-format` are no longer trimmed.
* `/boot` is hidden by default (FreeBSD, Disk)
Features:
* Add `--format json`, which prints system information as JSON format
* Add fast path for xfce4 version detection (DE, FreeBSD)
* Support contour terminal version and font detection (Terminal / TerminalFont)
* Support `kitty-direct` / `iterm` without specifying logo width / height. Note: in this case, the entre screen will be cleared.
* Support new flag `--logo-separate`. If true, print modules at bottom of the logo
* Support Apple Silicon CPU frequency detection (CPU, macOS)
* Support user login time detection (Users)
* Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows)
* Print monitor type (built-in or external) (Display)
* Support full GPU detection in WSL (Linux, GPU)
* Add `--module-key " "` as a special case for hiding keys
* Support `--title-format`. See `fastfetch --help title-format` for detail
* Support `--colors-key` (Colors)
* Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5
* Support Windows Service Pack version detection (Kernel, Windows)
* Support Debian point releases detection (OS, Linux)
* Add new module `NetIO` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish.
* Use `lscpu` to detect CPU name for ARM CPUs (CPU, Linux)
Bugfixes:
* Fix fastfetch hanging in specific environment (#561)
* Fix short read when reading from stdin (Logo)
* Fix `poll() timeout or failed` error when image is very large (Logo)
* Fix Termux Monet terminal version detection (Terminal)
* Fix zpool volumes detection (Disk, Linux)
* Fix external volumes detection (Disk, Linux)
* Fix snap package number detection on systems other than Ubuntu (Packages, Linux)
* Fix dpkg / apt package number detection (Packages, Linux)
* Fix bluetooth mac address detection (Bluetooth, Windows)
Logo:
* Add Afterglow
* Add Elbrus
* Update EvolutionOS
* Update AOSC OS
* Update Ubuntu_old
* Update Windows 11_small
* Add Amazon Linux
* Add LainOS
* Fix colors of Slackware
# 2.0.5
Bugfixes:
* Fix segfault when using libxrandr (#544, Display, Linux)
* Don't print 0px (#544, Cursor)
Features:
* Add option `--disk-use-available` (#543)
* Add option `--disk-show-readonly`
# 2.0.4
Bugfixes:
* Fix building on 32-bit FreeBSD (Memory, BSD)
* Fix building on 32-bit FreeBSD (Memory, FreeBSD)
* Fix `--file-raw` doesn't work (Logo)
Features:
+88 -8
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.0.4
VERSION 2.1.1
LANGUAGES C
DESCRIPTION "Fast system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -67,6 +67,7 @@ cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF)
@@ -98,10 +99,13 @@ set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=retu
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration")
if(WIN32)
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
enable_language(CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -fno-exceptions -fno-rtti")
endif()
if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
endif()
@@ -112,8 +116,8 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(NOT WIN32)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
if(NOT WIN32 AND NOT APPLE)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
@@ -121,8 +125,8 @@ if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic")
endif()
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Enabling LTO")
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
@@ -218,6 +222,9 @@ fastfetch_load_text(src/data/help_config.txt DATATEXT_HELP_CONFIG)
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
if(APPLE)
configure_file(src/util/apple/Info.plist.in Info.plist @ONLY)
endif()
####################
# Ascii image data #
@@ -259,6 +266,7 @@ set(LIBFASTFETCH_SRC
src/common/jsonconfig.c
src/common/library.c
src/common/modules.c
src/common/netif/netif.c
src/common/option.c
src/common/parsing.c
src/common/printing.c
@@ -267,20 +275,23 @@ set(LIBFASTFETCH_SRC
src/detection/chassis/chassis.c
src/detection/cpu/cpu.c
src/detection/cpuusage/cpuusage.c
src/detection/datetime/datetime.c
src/detection/disk/disk.c
src/detection/diskio/diskio.c
src/detection/displayserver/displayserver.c
src/detection/font/font.c
src/detection/gpu/gpu.c
src/detection/locale/locale.c
src/detection/media/media.c
src/detection/netio/netio.c
src/detection/opencl/opencl.c
src/detection/os/os.c
src/detection/packages/packages.c
src/detection/publicip/publicip.c
src/detection/terminalfont/terminalfont.c
src/detection/terminalshell/terminalshell.c
src/detection/version/version.c
src/detection/vulkan/vulkan.c
src/detection/weather/weather.c
src/logo/builtin.c
src/logo/image/im6.c
src/logo/image/im7.c
@@ -303,6 +314,7 @@ set(LIBFASTFETCH_SRC
src/modules/datetime/datetime.c
src/modules/de/de.c
src/modules/disk/disk.c
src/modules/diskio/diskio.c
src/modules/font/font.c
src/modules/gpu/gpu.c
src/modules/host/host.c
@@ -314,6 +326,7 @@ set(LIBFASTFETCH_SRC
src/modules/localip/localip.c
src/modules/memory/memory.c
src/modules/monitor/monitor.c
src/modules/netio/netio.c
src/modules/opencl/opencl.c
src/modules/opengl/opengl.c
src/modules/os/os.c
@@ -354,6 +367,7 @@ if(LINUX)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/netif/netif_linux.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_linux.c
@@ -366,6 +380,7 @@ if(LINUX)
src/detection/cursor/cursor_linux.c
src/detection/bluetooth/bluetooth_linux.c
src/detection/disk/disk_linux.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
@@ -376,12 +391,14 @@ if(LINUX)
src/detection/gtk_qt/gtk.c
src/detection/host/host_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_linux.c
src/detection/lm/lm_linux.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_linux.c
src/detection/media/media_linux.c
src/detection/memory/memory_linux.c
src/detection/monitor/monitor_linux.c
src/detection/netio/netio_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
@@ -405,6 +422,7 @@ if(LINUX)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/netif/netif_linux.c
src/common/networking_linux.c
src/common/processing_linux.c
src/detection/battery/battery_android.c
@@ -417,17 +435,20 @@ elseif(ANDROID)
src/detection/cursor/cursor_nosupport.c
src/detection/cpuusage/cpuusage_linux.c
src/detection/disk/disk_linux.c
src/detection/diskio/diskio_linux.c
src/detection/displayserver/displayserver_android.c
src/detection/font/font_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/host/host_android.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_android.c
src/detection/lm/lm_nosupport.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_nosupport.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_linux.c
src/detection/monitor/monitor_nosupport.c
src/detection/netio/netio_linux.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_android.c
src/detection/packages/packages_linux.c
@@ -451,6 +472,7 @@ elseif(BSD)
list(APPEND LIBFASTFETCH_SRC
src/common/dbus.c
src/common/io/io_unix.c
src/common/netif/netif_bsd.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
@@ -464,6 +486,7 @@ elseif(BSD)
src/detection/cpuusage/cpuusage_bsd.c
src/detection/cursor/cursor_linux.c
src/detection/disk/disk_bsd.c
src/detection/diskio/diskio_bsd.c
src/detection/displayserver/linux/displayserver_linux.c
src/detection/displayserver/linux/wayland.c
src/detection/displayserver/linux/wmde.c
@@ -475,11 +498,13 @@ elseif(BSD)
src/detection/host/host_bsd.c
src/detection/lm/lm_linux.c
src/detection/icons/icons_linux.c
src/detection/libc/libc_bsd.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_bsd.c
src/detection/media/media_linux.c
src/detection/memory/memory_bsd.c
src/detection/monitor/monitor_nosupport.c
src/detection/netio/netio_bsd.c
src/detection/opengl/opengl_linux.c
src/detection/os/os_linux.c
src/detection/packages/packages_linux.c
@@ -503,6 +528,7 @@ elseif(BSD)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_unix.c
src/common/netif/netif_bsd.c
src/common/networking_linux.c
src/common/processing_linux.c
src/common/sysctl.c
@@ -515,19 +541,21 @@ elseif(APPLE)
src/detection/cpu/cpu_apple.c
src/detection/cpuusage/cpuusage_apple.c
src/detection/cursor/cursor_apple.m
src/detection/disk/disk_apple.m
src/detection/disk/disk_bsd.c
src/detection/diskio/diskio_apple.c
src/detection/displayserver/displayserver_apple.c
src/detection/font/font_apple.m
src/detection/gpu/gpu_apple.c
src/detection/host/host_apple.c
src/detection/lm/lm_nosupport.c
src/detection/icons/icons_nosupport.c
src/detection/libc/libc_apple.c
src/detection/localip/localip_linux.c
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/monitor/monitor_apple.m
src/detection/netio/netio_bsd.c
src/detection/opengl/opengl_apple.c
src/detection/os/os_apple.m
src/detection/packages/packages_apple.c
@@ -552,6 +580,7 @@ elseif(APPLE)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
src/common/io/io_windows.c
src/common/netif/netif_windows.c
src/common/networking_windows.c
src/common/processing_windows.c
src/detection/battery/battery_windows.c
@@ -564,17 +593,20 @@ elseif(WIN32)
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
src/detection/disk/disk_windows.c
src/detection/diskio/diskio_windows.c
src/detection/displayserver/displayserver_windows.c
src/detection/font/font_windows.c
src/detection/gpu/gpu_windows.c
src/detection/host/host_windows.c
src/detection/icons/icons_windows.c
src/detection/libc/libc_windows.cpp
src/detection/lm/lm_nosupport.c
src/detection/localip/localip_windows.c
src/detection/gamepad/gamepad_windows.c
src/detection/media/media_nosupport.c
src/detection/memory/memory_windows.c
src/detection/monitor/monitor_windows.c
src/detection/netio/netio_windows.c
src/detection/opengl/opengl_windows.c
src/detection/os/os_windows.cpp
src/detection/packages/packages_windows.c
@@ -601,6 +633,11 @@ elseif(WIN32)
)
endif()
if(ENABLE_DIRECTX_HEADERS)
message(STATUS "Enabling DirectX headers for WSL")
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp)
endif()
include(CheckFunctionExists)
check_function_exists(wcwidth HAVE_WCWIDTH)
if(NOT HAVE_WCWIDTH)
@@ -623,14 +660,39 @@ endif()
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
if(yyjson_FOUND)
target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON)
target_link_libraries(libfastfetch PRIVATE yyjson)
endif()
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE)
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
ERROR_VARIABLE LD_MUSL_RESULT)
if("${LD_MUSL_RESULT}" MATCHES "Version ([0-9]+\\.[0-9]+\\.[0-9]+)")
target_compile_definitions(libfastfetch PUBLIC FF_MUSL_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(APPLE AND EXISTS "/usr/bin/otool")
execute_process(COMMAND /usr/bin/otool -L /usr/bin/otool
OUTPUT_VARIABLE OTOOL_OTOOL_RESULT)
if("${OTOOL_OTOOL_RESULT}" MATCHES "libSystem\\.B\\.dylib \\(.*current version ([0-9]+\\.[0-9]+\\.[0-9]+)\\)")
target_compile_definitions(libfastfetch PUBLIC FF_LIBSYSTEM_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
if(BSD AND EXISTS "/usr/local/bin/objdump")
execute_process(COMMAND /bin/sh -c "/usr/local/bin/objdump -T /lib/libc.so.* | grep 'FBSD_[^ )]*' -o | sort -Vru | head -1"
OUTPUT_VARIABLE OBJDUMP_T_RESULT)
if("${OBJDUMP_T_RESULT}" MATCHES "FBSD_([0-9]+\\.[0-9]+)")
target_compile_definitions(libfastfetch PUBLIC FF_FBSD_VERSION="${CMAKE_MATCH_1}")
endif()
endif()
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1)
if(WIN32)
target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1)
elseif(APPLE)
target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE)
endif()
if(HAVE_WCWIDTH)
@@ -773,6 +835,10 @@ ff_lib_enable(DDCUTIL
"ddcutil"
"Ddcutil"
)
ff_lib_enable(DIRECTX_HEADERS
"DirectX-Headers"
"DirectX-Headers"
)
if(ENABLE_THREADS)
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
@@ -827,6 +893,7 @@ elseif(BSD)
target_link_libraries(libfastfetch
PRIVATE "m"
PRIVATE "usbhid"
PRIVATE "devstat"
)
elseif(ANDROID)
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
@@ -877,6 +944,12 @@ target_link_libraries(flashfetch
PRIVATE libfastfetch
)
# Prevent fastfetch from linking to libstdc++
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
if(WIN32)
set(TARGET_NAME fastfetch)
target_sources(fastfetch
@@ -887,6 +960,13 @@ if(WIN32)
target_sources(flashfetch
PRIVATE src/util/windows/version.rc
)
elseif(APPLE)
target_link_options(fastfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
target_link_options(flashfetch
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
)
endif()
###################
+9 -6
View File
@@ -71,6 +71,7 @@ The following libraries are used if present at runtime:
* [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection.
* [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection.
* [`libddcutil`](https://github.com/rockowitz/ddcutil): Used for brightness detection of external displays
* [`DirectX-Headers`](https://github.com/microsoft/DirectX-Headers): Used for GPU detection in WSL
### macOS
@@ -91,35 +92,37 @@ For the image logo, iTerm with iterm image protocol should work. Apple Terminal
Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later.
For the image logo, only chafa is supported due to [a design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not included by default due to the massive dependencies of imagemagick. You must built it yourself.
For the image logo, WezTerm with iterm image protocol is known to work, surprisingly.
### Android
* [`freetype`](https://www.freetype.org/): Used for Termux font detection. [`freetype`](https://github.com/termux/termux-packages/tree/master/packages/freetype)
* [`libvulkan`](https://www.vulkan.org/): Vulkan module, also used for GPU detection. Usually has been provided by Android system. [`vulkan-loader-android`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-loader-android) [`vulkan-headers`](https://github.com/termux/termux-packages/tree/master/packages/vulkan-headers)
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api)
* [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Both the package [termux-api](https://github.com/termux/termux-packages/tree/master/packages/termux-api) and the Android app [Termux API](https://github.com/termux/termux-api) must be installed and the app `Termux API` must be configured to be able to self-running. In order to make Wifi detection actuall work, location privilege must be granted to the app `Termux API`. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail.
* [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android.
For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol.
## Support status
All categories not listed here should work without needing a specific implementation.
##### Available Modules
```
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme
Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, DiskIO, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme
```
##### Builtin logos
<!-- `Content of src/logo/builtin.c`.split('\n').map(x => x.trim()).filter(x => x.startsWith('// ')).map(x => x.slice(3)).filter(x => x != 'LAST').sort((a, b)=>a.toUpperCase().localeCompare(b.toUpperCase())).join(', ') -->
```
AerOS, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin
AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, Chimera Linux, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, EndeavourSmall, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LainOS, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xenia, Xferience, YiffOS, Zorin
```
Run `fastfetch --print-logos` to print them
##### Package managers
```
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps
apk, brew, Chocolatey, dpkg, emerge, eopkg, Flatpak, MacPorts, nix, opkg, Pacman, paludis, pkg, pkgtool, rpm, scoop, Snap, xbps
```
##### WM themes
@@ -134,7 +137,7 @@ Budgie, Cinnamon, Gnome, KDE Plasma, LXQt, Mate, XFCE4
##### Terminal fonts
```
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake
Alacritty, Apple Terminal, ConEmu, Deepin Terminal, foot, Gnome Console, Gnome Terminal, iTerm2, Kitty, Konsole, LXTerminal, MATE Terminal, mintty, QTerminal, Tabby, Terminator, Termux, Tilix, TTY, Warp, WezTerm, Windows Terminal, XFCE4 Terminal, Yakuake
```
## Building
+1 -1
View File
@@ -24,7 +24,7 @@ __fastfetch_complete_help()
"terminal-format"
"terminalfont-format"
"cpu-format"
"cpu-usage-format"
"cpuusage-format"
"gpu-format"
"memory-format"
"swap-format"
+279 -43
View File
@@ -166,6 +166,11 @@
"title": "If true, regenerate image logo cache",
"default": false
},
"separate": {
"type": "boolean",
"title": "If true, print modules at bottom of the logo",
"default": false
},
"chafa": {
"type": "object",
"title": "Chafa configuration. See chafa document for details",
@@ -269,6 +274,11 @@
"type": "integer",
"title": "Set the timeout (ms) for WMI queries, `-1` for no timeout. Windows only",
"default": 5000
},
"processingTimeout": {
"type": "integer",
"title": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout",
"default": 1000
}
},
"additionalProperties": false
@@ -535,6 +545,7 @@
"datetime",
"display",
"disk",
"diskio",
"de",
"font",
"gamepad",
@@ -548,6 +559,7 @@
"media",
"memory",
"monitor",
"netio",
"opencl",
"opengl",
"os",
@@ -584,7 +596,6 @@
],
"properties": {
"type": {
"title": "Module type",
"type": "string"
}
},
@@ -603,45 +614,151 @@
"title": "No additional properties",
"properties": {
"type": {
"enum": [
"bios",
"board",
"brightness",
"chassis",
"cpuusage",
"cursor",
"datetime",
"de",
"font",
"gamepad",
"host",
"icons",
"kernel",
"lm",
"locale",
"media",
"memory",
"monitor",
"opencl",
"os",
"packages",
"player",
"poweradapter",
"processes",
"shell",
"swap",
"terminal",
"terminalfont",
"terminalsize",
"theme",
"uptime",
"users",
"version",
"vulkan",
"wallpaper",
"wm",
"wifi",
"wmtheme"
"anyOf": [
{
"const": "bios",
"description": "Print BIOS name, version, release date, etc"
},
{
"const": "board",
"description": "Print mather board name and other info"
},
{
"const": "chassis",
"description": "Print chassis type (desktop, laptop, etc)"
},
{
"const": "cursor",
"description": "Print cursor style name"
},
{
"const": "datetime",
"description": "Print current date and time"
},
{
"const": "de",
"description": "Print desktop environment name"
},
{
"const": "font",
"description": "Print system font name"
},
{
"const": "gamepad",
"description": "List connected gamepads"
},
{
"const": "host",
"description": "Print product name of your computer"
},
{
"const": "icons",
"description": "Print icon style name"
},
{
"const": "kernel",
"description": "Print system kernel version"
},
{
"const": "lm",
"description": "Print login manager (desktop manager) name and version"
},
{
"const": "locale",
"description": "Print system locale name"
},
{
"const": "media",
"description": "Print playing song name"
},
{
"const": "memory",
"description": "Print system memory usage info"
},
{
"const": "monitor",
"description": "Print connected physical monitor information"
},
{
"const": "opencl",
"description": "Print highest OpenCL version supported by the GPU"
},
{
"const": "os",
"description": "Print operating system name and version"
},
{
"const": "packages",
"description": "List installed package managers and count of installed packages"
},
{
"const": "player",
"description": "Print music player name"
},
{
"const": "poweradapter",
"description": "Print power adapter name and charging watts"
},
{
"const": "processes",
"description": "Count running processes"
},
{
"const": "shell",
"description": "Print current shell name and version"
},
{
"const": "swap",
"description": "Print swap (paging file) space usage"
},
{
"const": "terminal",
"description": "Print current terminal name and version"
},
{
"const": "terminalfont",
"description": "Print font name and size used by current terminal"
},
{
"const": "terminalsize",
"description": "Print current terminal size"
},
{
"const": "theme",
"description": "Print current theme information"
},
{
"const": "uptime",
"description": "Print system uptime"
},
{
"const": "users",
"description": "List users currently logged in"
},
{
"const": "version",
"description": "Print Fastfetch version"
},
{
"const": "vulkan",
"description": "Print highest Vulkan version supported by the GPU"
},
{
"const": "wallpaper",
"description": "Print image file path of current wallpaper"
},
{
"const": "wm",
"description": "Print window manager name and version"
},
{
"const": "wifi",
"description": "Print connected Wi-Fi info (SSID, connection and security protocol)"
},
{
"const": "wmtheme",
"description": "Print current theme of window manager"
}
]
},
"key": {
@@ -663,7 +780,8 @@
"title": "Battery",
"properties": {
"type": {
"const": "battery"
"const": "battery",
"description": "Print battery capacity, status, etc"
},
"dir": {
"title": "The directory where the battery folders are. Standard: `/sys/class/power_supply/`. Linux only",
@@ -693,6 +811,7 @@
"title": "Bluetooth",
"properties": {
"type": {
"description": "List bluetooth devices",
"const": "bluetooth"
},
"showDisconnected": {
@@ -715,10 +834,27 @@
},
"additionalProperties": false
},
{
"title": "Brightness",
"properties": {
"type": {
"const": "brightness",
"description": "Print current brightness / luminance of your monitors"
},
"ddcciSleep": {
"type": "integer",
"description": "Set the sleep times (in ms) when sending DDC/CI requests.\nSee <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail",
"minimum": 0,
"maximum": 400,
"default": 10
}
}
},
{
"title": "CPU",
"properties": {
"type": {
"description": "Print CPU name, frequency, etc",
"const": "cpu"
},
"temp": {
@@ -726,6 +862,13 @@
"type": "boolean",
"default": false
},
"freqNdigits": {
"title": "Set the number of digits to keep after the decimal point when printing CPU frequency",
"type": "integer",
"minimum": 0,
"maximum": 9,
"default": 2
},
"key": {
"$ref": "#/$defs/key"
},
@@ -741,10 +884,25 @@
},
"additionalProperties": false
},
{
"title": "CPU Usage",
"properties": {
"type": {
"const": "cpuusage",
"description": "Print CPU usage. Costs some time to collect data"
},
"separate": {
"type": "boolean",
"description": "Display CPU usage per CPU logical core, instead of an average result",
"default": false
}
}
},
{
"title": "Colors",
"properties": {
"type": {
"description": "Print some colored blocks",
"const": "colors"
},
"symbol": {
@@ -772,6 +930,7 @@
"title": "Command",
"properties": {
"type": {
"description": "Running custom shell scripts",
"const": "command"
},
"shell": {
@@ -799,9 +958,9 @@
},
{
"title": "Custom",
"description": "Print a custom string, with or without key",
"properties": {
"type": {
"description": "Print a custom string, with or without key",
"const": "custom"
},
"key": {
@@ -828,6 +987,7 @@
"title": "Display",
"properties": {
"type": {
"description": "Print resolutions, refresh rates, etc",
"const": "display"
},
"compactType": {
@@ -863,6 +1023,7 @@
"title": "Disk",
"properties": {
"type": {
"description": "Print partitions, space usage, disk type, etc",
"const": "disk"
},
"folders": {
@@ -884,11 +1045,47 @@
"title": "Set if subvolumes should be printed",
"default": false
},
"showReadOnly": {
"type": "boolean",
"title": "Set if read only volumes should be printed",
"default": false
},
"showUnknown": {
"type": "boolean",
"title": "Set if unknown (unable to detect sizes) volumes should be printed",
"default": false
},
"useAvailable": {
"type": "boolean",
"title": "Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
},
{
"title": "DiskIO",
"properties": {
"type": {
"description": "Print physical disk I/O throughput",
"const": "diskio"
},
"namePrefix": {
"title": "Show disks with given name prefix only",
"type": "string"
},
"key": {
"$ref": "#/$defs/key"
},
@@ -908,6 +1105,7 @@
"title": "GPU",
"properties": {
"type": {
"description": "Print GPU names, graphic memory size, type, etc",
"const": "gpu"
},
"temp": {
@@ -948,6 +1146,7 @@
"title": "Local IP",
"properties": {
"type": {
"description": "List local IP addresses (v4 or v6), MAC addresses, etc",
"const": "localip"
},
"showIpv4": {
@@ -979,7 +1178,38 @@
"title": "Show IPs with given name prefix only",
"type": "string"
},
"showDefaultRouteOnly": {
"defaultRouteOnly": {
"title": "Show ips that are used for default routing only",
"type": "boolean",
"default": false
},
"key": {
"$ref": "#/$defs/key"
},
"keyColor": {
"$ref": "#/$defs/keyColor"
},
"keyWidth": {
"$ref": "#/$defs/keyWidth"
},
"format": {
"$ref": "#/$defs/format"
}
},
"additionalProperties": false
},
{
"title": "NetIO",
"properties": {
"type": {
"description": "Print network I/O throughput",
"const": "netio"
},
"namePrefix": {
"title": "Show IPs with given name prefix only",
"type": "string"
},
"defaultRouteOnly": {
"title": "Show ips that are used for default routing only",
"type": "boolean",
"default": false
@@ -1003,6 +1233,7 @@
"title": "OpenGL",
"properties": {
"type": {
"description": "Print highest OpenGL version supported by the GPU",
"const": "opengl"
},
"library": {
@@ -1034,6 +1265,7 @@
"title": "Public IP",
"properties": {
"type": {
"description": "Print your public IP address, etc",
"const": "publicip"
},
"url": {
@@ -1067,6 +1299,7 @@
"title": "Separator",
"properties": {
"type": {
"description": "Print a separator line",
"const": "separator"
},
"string": {
@@ -1081,6 +1314,7 @@
"title": "Sound",
"properties": {
"type": {
"description": "Print sound devices, volume, etc",
"const": "sound"
},
"soundType": {
@@ -1112,6 +1346,7 @@
"title": "Title",
"properties": {
"type": {
"description": "Print title, which contains your user name, hostname",
"const": "title"
},
"fqdn": {
@@ -1156,6 +1391,7 @@
"title": "Weather",
"properties": {
"type": {
"description": "Print weather information",
"const": "weather"
},
"location": {
+1 -1
View File
@@ -1 +1 @@
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Version:Break:Colors
--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:DiskIO:Version:Break:Colors
+2
View File
@@ -51,6 +51,8 @@
"sound",
"gamepad",
"weather",
"netio",
"diskio",
"version",
"break",
"colors"
+7
View File
@@ -0,0 +1,7 @@
-c all
--pipe
--show-errors
--no-buffer
--publicip-timeout 1000
--weather-timeout 1000
--stat
-3
View File
@@ -1,3 +0,0 @@
--disable-linewrap false
--multithreading false
--show-errors
-3
View File
@@ -1,3 +0,0 @@
--load-config devinfo
--load-config all
--load-config verbose
-49
View File
@@ -1,49 +0,0 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "builtin",
"source": "arch"
},
"display": {
"disableLinewrap": false,
"showErrors": true
},
"general": {
"multithreading": false
},
"modules": [
"title",
"separator",
{
"type": "os",
"format": "Arch Linux ({12})"
},
"host",
"kernel",
"uptime",
{
"type": "packages",
"format": "{} (pacman)"
},
"shell",
"display",
"de",
"wm",
"wmtheme",
"theme",
"icons",
"font",
"cursor",
"terminal",
"terminalfont",
"cpu",
"gpu",
"memory",
"disk",
"battery",
"poweradapter",
"locale",
"break",
"colors"
]
}
+150
View File
@@ -0,0 +1,150 @@
// Load with --load-config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"padding": {
"top": 2
}
},
"display": {
"separator": " -> "
},
"modules": [
{
"type": "custom",
"format": "\u001b[90m┌────────────────────────────────────────────────────────────┐"
},
{
"type": "title",
"keyWidth": 10
},
{
"type": "custom",
"format": "\u001b[90m└────────────────────────────────────────────────────────────┘"
},
{
"type": "custom",
"format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m  \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m"
},
{
"type": "custom",
"format": "\u001b[90m┌────────────────────────────────────────────────────────────┐"
},
{
"type": "os",
"key": " OS",
"keyColor": "yellow"
},
{
"type": "kernel",
"key": "│ ├",
"keyColor": "yellow"
},
{
"type": "packages",
"key": "│ ├󰏖",
"keyColor": "yellow"
},
{
"type": "shell",
"key": "│ └",
"keyColor": "yellow"
},
{
"type": "wm",
"key": " DE/WM",
"keyColor": "blue"
},
{
"type": "lm",
"key": "│ ├󰧨",
"keyColor": "blue"
},
{
"type": "wmtheme",
"key": "│ ├󰉼",
"keyColor": "blue"
},
{
"type": "icons",
"key": "│ ├󰀻",
"keyColor": "blue"
},
{
"type": "terminal",
"key": "│ ├",
"keyColor": "blue"
},
{
"type": "wallpaper",
"key": "│ └󰸉",
"keyColor": "blue"
},
{
"type": "host",
"key": " PC",
"keyColor": "green"
},
{
"type": "cpu",
"key": "│ ├",
"keyColor": "green"
},
{
"type": "gpu",
"key": "│ ├﬙",
"keyColor": "green"
},
{
"type": "disk",
"key": "│ ├",
"keyColor": "green"
},
{
"type": "memory",
"key": "│ ├󰑭",
"keyColor": "green"
},
{
"type": "swap",
"key": "│ ├󰓡",
"keyColor": "green"
},
{
"type": "uptime",
"key": "│ ├󰅐",
"keyColor": "green"
},
{
"type": "display",
"key": "│ └󰍹",
"keyColor": "green"
},
{
"type": "sound",
"key": " SND",
"keyColor": "cyan"
},
{
"type": "player",
"key": "│ ├󰥠",
"keyColor": "cyan"
},
{
"type": "media",
"key": "│ └󰝚",
"keyColor": "cyan"
},
{
"type": "custom",
"format": "\u001b[90m└────────────────────────────────────────────────────────────┘"
},
"break",
{
"type": "custom",
"format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m  \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m"
}
]
}
+38
View File
@@ -0,0 +1,38 @@
{
"$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json",
"logo": {
"type": "small"
},
"display": {
"percentType": 9,
"separator": "\u001b[31m-> "
},
"modules": [
{
"key": "Distro ",
"type": "os"
},
{
"key": "Shell ",
"type": "shell"
},
{
"key": "Terminal ",
"type": "terminal"
},
{
"key": "Display ",
"type": "display"
},
{
"key": "Backlight ",
"type": "brightness"
},
"break",
{
"type": "colors",
"paddingLeft": 6,
"symbol": "circle"
}
]
}
-31
View File
@@ -1,31 +0,0 @@
--os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {}
--host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {}
--kernel-format Sysname: {}; Release: {}; Version: {}
--uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {}
--processes-format Count: {}
--packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak-system: {}; flatpak-user: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}; pkgtool: {}; paludis {}
--shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {}
--display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {}
--de-format Process name: {}; Pretty name: {}; Version: {}
--wm-format Process name: {}; Pretty name: {}; Protocol: {}
--wmtheme-format Name: {}
--theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
--icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {}
--font-format Font1: {}; Font2: {}; Font3: {}; Font4: {}
--cursor-format Theme: {}; Size: {}
--terminal-format Process: {}; Path: {}; Exe: {}
--terminalfont-format Pretty: {}; Name: {}; Size: {}; Styles: {}
--cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {}
--cpu-usage-format Percentage: {}
--gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {}
--memory-format Used: {}; Total: {}; Percentage: {}
--disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; External: {}; Hidden: {}; Filesystem: {}; Name: {}
--battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {}
--poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {}
--player-format Pretty: {}; Name: {}; Bus: {}; Url: {}
--media-format Pretty: {}; Name: {}; Artist: {}; Album: {}
--datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {}
--vulkan-format driver: {}; Api Version: {}; Conformance Version: {}
--opengl-format version: {}; renderer: {}; vendor: {}
--opencl-format version: {}; device: {}; vendor: {}
--bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"home": "https://github.com/ibireme/yyjson",
"license": "MIT ( embed in source )",
"version": "5e3b26d2659287d31e2f8e10f95f95feb7e5ab3a",
"version": "0.8.0",
"author": "ibireme"
}
+217 -51
View File
@@ -307,6 +307,9 @@ uint32_t yyjson_version(void) {
#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val))
#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val))
/* The minimum size of the dynamic allocator's chunk. */
#define YYJSON_ALC_DYN_MIN_SIZE 0x1000
/* Default value for compile-time options. */
#ifndef YYJSON_DISABLE_READER
#define YYJSON_DISABLE_READER 0
@@ -966,6 +969,15 @@ static const yyjson_alc YYJSON_DEFAULT_ALC = {
NULL
};
/*==============================================================================
* Null Memory Allocator
*
* This allocator is just a placeholder to ensure that the internal
* malloc/realloc/free function pointers are not null.
*============================================================================*/
static void *null_malloc(void *ctx, usize size) {
return NULL;
}
@@ -989,29 +1001,37 @@ static const yyjson_alc YYJSON_NULL_ALC = {
/*==============================================================================
* Pool Memory Allocator
* This is a simple memory allocator that uses linked list memory chunk.
* The following code will be executed only when the library user creates
* this allocator manually.
*
* This allocator is initialized with a fixed-size buffer.
* The buffer is split into multiple memory chunks for memory allocation.
*============================================================================*/
/** chunk header */
/** memory chunk header */
typedef struct pool_chunk {
usize size; /* chunk memory size (include chunk header) */
struct pool_chunk *next;
usize size; /* chunk memory size, include chunk header */
struct pool_chunk *next; /* linked list, nullable */
/* char mem[]; flexible array member */
} pool_chunk;
/** ctx header */
/** allocator ctx header */
typedef struct pool_ctx {
usize size; /* total memory size (include ctx header) */
pool_chunk *free_list;
usize size; /* total memory size, include ctx header */
pool_chunk *free_list; /* linked list, nullable */
/* pool_chunk chunks[]; flexible array member */
} pool_ctx;
/** align up the input size to chunk size */
static_inline void pool_size_align(usize *size) {
*size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk);
}
static void *pool_malloc(void *ctx_ptr, usize size) {
/* assert(size != 0) */
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
pool_chunk *next, *prev = NULL, *cur = ctx->free_list;
if (unlikely(size == 0 || size >= ctx->size)) return NULL;
size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk);
if (unlikely(size >= ctx->size)) return NULL;
pool_size_align(&size);
while (cur) {
if (cur->size < size) {
@@ -1038,6 +1058,7 @@ static void *pool_malloc(void *ctx_ptr, usize size) {
}
static void pool_free(void *ctx_ptr, void *ptr) {
/* assert(ptr != NULL) */
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
pool_chunk *cur = ((pool_chunk *)ptr) - 1;
pool_chunk *prev = NULL, *next = ctx->free_list;
@@ -1064,25 +1085,15 @@ static void pool_free(void *ctx_ptr, void *ptr) {
static void *pool_realloc(void *ctx_ptr, void *ptr,
usize old_size, usize size) {
/* assert(ptr != NULL && size != 0 && old_size < size) */
pool_ctx *ctx = (pool_ctx *)ctx_ptr;
pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp;
usize free_size;
void *new_ptr;
if (unlikely(size == 0 || size >= ctx->size)) return NULL;
size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk);
/* reduce size */
if (unlikely(size <= cur->size)) {
free_size = cur->size - size;
if (free_size >= sizeof(pool_chunk) * 2) {
tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size);
tmp->size = free_size;
pool_free(ctx_ptr, (void *)(tmp + 1));
cur->size -= free_size;
}
return ptr;
}
/* check size */
if (unlikely(size >= ctx->size)) return NULL;
pool_size_align(&old_size);
pool_size_align(&size);
if (unlikely(old_size == size)) return ptr;
/* find next and prev chunk */
prev = NULL;
@@ -1092,10 +1103,9 @@ static void *pool_realloc(void *ctx_ptr, void *ptr,
next = next->next;
}
/* merge to higher chunk if they are contiguous */
if ((u8 *)cur + cur->size == (u8 *)next &&
cur->size + next->size >= size) {
free_size = cur->size + next->size - size;
if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) {
/* merge to higher chunk if they are contiguous */
usize free_size = cur->size + next->size - size;
if (free_size > sizeof(pool_chunk) * 2) {
tmp = (pool_chunk *)(void *)((u8 *)cur + size);
if (prev) prev->next = tmp;
@@ -1109,15 +1119,15 @@ static void *pool_realloc(void *ctx_ptr, void *ptr,
cur->size += next->size;
}
return ptr;
} else {
/* fallback to malloc and memcpy */
void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk));
if (new_ptr) {
memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk));
pool_free(ctx_ptr, ptr);
}
return new_ptr;
}
/* fallback to malloc and memcpy */
new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk));
if (new_ptr) {
memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk));
pool_free(ctx_ptr, ptr);
}
return new_ptr;
}
bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) {
@@ -1147,6 +1157,161 @@ bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) {
/*==============================================================================
* Dynamic Memory Allocator
*
* This allocator allocates memory on demand and does not immediately release
* unused memory. Instead, it places the unused memory into a freelist for
* potential reuse in the future. It is only when the entire allocator is
* destroyed that all previously allocated memory is released at once.
*============================================================================*/
/** memory chunk header */
typedef struct dyn_chunk {
usize size; /* chunk size, include header */
struct dyn_chunk *next;
/* char mem[]; flexible array member */
} dyn_chunk;
/** allocator ctx header */
typedef struct {
dyn_chunk free_list; /* dummy header, sorted from small to large */
dyn_chunk used_list; /* dummy header */
} dyn_ctx;
/** align up the input size to chunk size */
static_inline bool dyn_size_align(usize *size) {
usize alc_size = *size + sizeof(dyn_chunk);
alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE);
if (unlikely(alc_size < *size)) return false; /* overflow */
*size = alc_size;
return true;
}
/** remove a chunk from list (the chunk must already be in the list) */
static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) {
dyn_chunk *prev = list, *cur;
for (cur = prev->next; cur; cur = cur->next) {
if (cur == chunk) {
prev->next = cur->next;
cur->next = NULL;
return;
}
prev = cur;
}
}
/** add a chunk to list header (the chunk must not be in the list) */
static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) {
chunk->next = list->next;
list->next = chunk;
}
static void *dyn_malloc(void *ctx_ptr, usize size) {
/* assert(size != 0) */
const yyjson_alc def = YYJSON_DEFAULT_ALC;
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
dyn_chunk *chunk, *prev, *next;
if (unlikely(!dyn_size_align(&size))) return NULL;
/* freelist is empty, create new chunk */
if (!ctx->free_list.next) {
chunk = (dyn_chunk *)def.malloc(def.ctx, size);
if (unlikely(!chunk)) return NULL;
chunk->size = size;
chunk->next = NULL;
dyn_chunk_list_add(&ctx->used_list, chunk);
return (void *)(chunk + 1);
}
/* find a large enough chunk, or resize the largest chunk */
prev = &ctx->free_list;
while (true) {
chunk = prev->next;
if (chunk->size >= size) { /* enough size, reuse this chunk */
prev->next = chunk->next;
dyn_chunk_list_add(&ctx->used_list, chunk);
return (void *)(chunk + 1);
}
if (!chunk->next) { /* resize the largest chunk */
chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
if (unlikely(!chunk)) return NULL;
prev->next = NULL;
chunk->size = size;
dyn_chunk_list_add(&ctx->used_list, chunk);
return (void *)(chunk + 1);
}
prev = chunk;
}
}
static void *dyn_realloc(void *ctx_ptr, void *ptr,
usize old_size, usize size) {
/* assert(ptr != NULL && size != 0 && old_size < size) */
const yyjson_alc def = YYJSON_DEFAULT_ALC;
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
dyn_chunk *prev, *next, *new_chunk;
dyn_chunk *chunk = (dyn_chunk *)ptr - 1;
if (unlikely(!dyn_size_align(&size))) return NULL;
if (chunk->size >= size) return ptr;
dyn_chunk_list_remove(&ctx->used_list, chunk);
new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
if (likely(new_chunk)) {
new_chunk->size = size;
chunk = new_chunk;
}
dyn_chunk_list_add(&ctx->used_list, chunk);
return new_chunk ? (void *)(new_chunk + 1) : NULL;
}
static void dyn_free(void *ctx_ptr, void *ptr) {
/* assert(ptr != NULL) */
dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev;
dyn_chunk_list_remove(&ctx->used_list, chunk);
for (prev = &ctx->free_list; prev; prev = prev->next) {
if (!prev->next || prev->next->size >= chunk->size) {
chunk->next = prev->next;
prev->next = chunk;
break;
}
}
}
yyjson_alc *yyjson_alc_dyn_new(void) {
const yyjson_alc def = YYJSON_DEFAULT_ALC;
usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx);
yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len);
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
if (unlikely(!alc)) return NULL;
alc->malloc = dyn_malloc;
alc->realloc = dyn_realloc;
alc->free = dyn_free;
alc->ctx = alc + 1;
memset(ctx, 0, sizeof(*ctx));
return alc;
}
void yyjson_alc_dyn_free(yyjson_alc *alc) {
const yyjson_alc def = YYJSON_DEFAULT_ALC;
dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
dyn_chunk *chunk, *next;
if (unlikely(!alc)) return;
for (chunk = ctx->free_list.next; chunk; chunk = next) {
next = chunk->next;
def.free(def.ctx, chunk);
}
for (chunk = ctx->used_list.next; chunk; chunk = next) {
next = chunk->next;
def.free(def.ctx, chunk);
}
def.free(def.ctx, alc);
}
/*==============================================================================
* JSON document and value
*============================================================================*/
@@ -1305,7 +1470,6 @@ yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc,
We copy them to another contiguous memory as mutable values,
then reconnect the mutable values with the original relationship.
*/
usize i_vals_len;
yyjson_mut_val *m_vals, *m_val;
yyjson_val *i_val, *i_end;
@@ -1375,7 +1539,6 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc,
second to last item, which needs to be linked to the last item to close the
circle.
*/
yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1);
if (unlikely(!m_val)) return NULL;
m_val->tag = m_vals->tag;
@@ -1540,12 +1703,13 @@ static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) {
yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni;
yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs);
yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs);
if (lt == rt)
return luni->u64 == runi->u64;
if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT)
if (lt == rt) return luni->u64 == runi->u64;
if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) {
return luni->i64 >= 0 && luni->u64 == runi->u64;
if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT)
}
if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) {
return runi->i64 >= 0 && luni->u64 == runi->u64;
}
return false;
}
@@ -1571,8 +1735,8 @@ bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
while (len-- > 0) {
rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str,
unsafe_yyjson_get_len(lhs));
if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs))
return false;
if (!rhs) return false;
if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false;
lhs = unsafe_yyjson_get_next(lhs + 1);
}
}
@@ -1626,8 +1790,8 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) {
while (len-- > 0) {
rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str,
unsafe_yyjson_get_len(lhs));
if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs))
return false;
if (!rhs) return false;
if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false;
lhs = lhs->next->next;
}
}
@@ -2506,6 +2670,7 @@ yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
builder = yyjson_mut_obj(doc);
if (unlikely(!builder)) return NULL;
memset(&local_orig, 0, sizeof(local_orig));
if (!yyjson_is_obj(orig)) {
orig = &local_orig;
orig->tag = builder->tag;
@@ -2557,6 +2722,7 @@ yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
builder = yyjson_mut_obj(doc);
if (unlikely(!builder)) return NULL;
memset(&local_orig, 0, sizeof(local_orig));
if (!yyjson_mut_is_obj(orig)) {
orig = &local_orig;
orig->tag = builder->tag;
@@ -3318,8 +3484,6 @@ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) {
#if !YYJSON_DISABLE_READER
/*==============================================================================
* JSON Character Matcher
*============================================================================*/
@@ -3513,6 +3677,8 @@ static_inline bool digi_is_digit_or_fp(u8 d) {
#if !YYJSON_DISABLE_READER
/*==============================================================================
* Hex Character Reader
* This function is used by JSON reader to read escaped characters.
+85 -21
View File
@@ -527,16 +527,16 @@ extern "C" {
#define YYJSON_VERSION_MAJOR 0
/** The minor version of yyjson. */
#define YYJSON_VERSION_MINOR 7
#define YYJSON_VERSION_MINOR 8
/** The patch version of yyjson. */
#define YYJSON_VERSION_PATCH 0
/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
#define YYJSON_VERSION_HEX 0x000700
#define YYJSON_VERSION_HEX 0x000800
/** The version string of yyjson. */
#define YYJSON_VERSION_STRING "0.7.0"
#define YYJSON_VERSION_STRING "0.8.0"
/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
yyjson_api uint32_t yyjson_version(void);
@@ -635,11 +635,11 @@ typedef struct yyjson_alc {
function, but the amount of memory required to write a JSON cannot be directly
calculated.
This is not a general-purpose allocator. If used to read multiple JSON
documents and only some of them are released, it may cause memory
fragmentation, leading to performance degradation and memory waste. Therefore,
it is recommended to use this allocator only for reading or writing a single
JSON document.
This is not a general-purpose allocator. It is designed to handle a single JSON
data at a time. If it is used for overly complex memory tasks, such as parsing
multiple JSON documents using the same allocator but releasing only a few of
them, it may cause memory fragmentation, resulting in performance degradation
and memory waste.
@param alc The allocator to be initialized.
If this parameter is NULL, the function will fail and return false.
@@ -662,9 +662,31 @@ typedef struct yyjson_alc {
yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL);
// the memory of `doc` is on the stack
@endcode
@warning This Allocator is not thread-safe.
*/
yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size);
/**
A dynamic allocator.
This allocator has a similar usage to the pool allocator above. However, when
there is not enough memory, this allocator will dynamically request more memory
using libc's `malloc` function, and frees it all at once when it is destroyed.
@return A new dynamic allocator, or NULL if memory allocation failed.
@note The returned value should be freed with `yyjson_alc_dyn_free()`.
@warning This Allocator is not thread-safe.
*/
yyjson_api yyjson_alc *yyjson_alc_dyn_new(void);
/**
Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`.
@param alc The dynamic allocator to be destroyed.
*/
yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc);
/*==============================================================================
@@ -3556,7 +3578,7 @@ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3566,7 +3588,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3576,7 +3598,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3586,7 +3608,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3596,7 +3618,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3606,7 +3628,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3616,7 +3638,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3626,7 +3648,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3636,7 +3658,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
The `key` and `val` should be null-terminated UTF-8 strings.
This function allows duplicated key in one object.
@warning The key/value string are not copied, you should keep these strings
@warning The key/value strings are not copied, you should keep these strings
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3648,7 +3670,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
The `len` should be the length of the `val`, in bytes.
This function allows duplicated key in one object.
@warning The key/value string are not copied, you should keep these strings
@warning The key/value strings are not copied, you should keep these strings
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3660,7 +3682,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
The value string is copied.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -3673,18 +3695,44 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
The `len` should be the length of the `val`, in bytes.
This function allows duplicated key in one object.
@warning The key/value string are not copied, you should keep these strings
@warning The key/value strings are not copied, you should keep these strings
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *key,
const char *val, size_t len);
/**
Creates and adds a new array to the target object.
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string is not copied, you should keep these strings
unmodified for the lifetime of this JSON document.
@return The new array, or NULL on error.
*/
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *key);
/**
Creates and adds a new object to the target object.
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string is not copied, you should keep these strings
unmodified for the lifetime of this JSON document.
@return The new object, or NULL on error.
*/
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *key);
/** Adds a JSON value at the end of the object.
The `key` should be a null-terminated UTF-8 string.
This function allows duplicated key in one object.
@warning The key string are not copied, you should keep the string
@warning The key string is not copied, you should keep the string
unmodified for the lifetime of this JSON document. */
yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
@@ -6920,6 +6968,22 @@ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
});
}
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *_key) {
yyjson_mut_val *key = yyjson_mut_str(doc, _key);
yyjson_mut_val *val = yyjson_mut_arr(doc);
return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
}
yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *_key) {
yyjson_mut_val *key = yyjson_mut_str(doc, _key);
yyjson_mut_val *val = yyjson_mut_obj(doc);
return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
}
yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *_key,
+112 -1
View File
@@ -1,7 +1,26 @@
#include "commandoption.h"
#include "common/printing.h"
#include "common/time.h"
#include "fastfetch_datatext.h"
#include "modules/modules.h"
#include "util/stringUtils.h"
#include <ctype.h>
#include <inttypes.h>
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
{
yyjson_mut_doc* doc = instance.state.resultDoc;
if (__builtin_expect(!doc, true)) return NULL;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJson)
baseInfo->generateJson(baseInfo, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
return module;
}
bool ffParseModuleCommand(const char* type)
{
@@ -12,7 +31,8 @@ bool ffParseModuleCommand(const char* type)
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrEqualsIgnCase(type, baseInfo->name))
{
baseInfo->printModule(baseInfo);
if (!genJson(baseInfo))
baseInfo->printModule(baseInfo);
return true;
}
}
@@ -30,3 +50,94 @@ bool ffParseModuleOptions(const char* key, const char* value)
}
return false;
}
void ffPrepareCommandOption(FFdata* data)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE);
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
ffPrepareCPUUsage();
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
ffPrepareDiskIO(&instance.config.diskIo);
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
ffPrepareNetIO(&instance.config.netIo);
if(instance.config.multithreading)
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
ffPreparePublicIp(&instance.config.publicIP);
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
ffPrepareWeather(&instance.config.weather);
}
}
static void parseStructureCommand(const char* line, FFlist* customValues)
{
// handle `--set` and `--set-keyless`
FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues)
{
if (ffStrbufEqualS(&customValue->key, line))
{
__attribute__((__cleanup__(ffDestroyCustomOptions))) FFCustomOptions options;
ffInitCustomOptions(&options);
if (customValue->printKey)
ffStrbufAppend(&options.moduleArgs.key, &customValue->key);
ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value);
ffPrintCustom(&options);
return;
}
}
if(!ffParseModuleCommand(line))
ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
void ffPrintCommandOption(FFdata* data)
{
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
uint64_t ms = 0;
if(instance.config.stat)
ms = ffTimeGetTick();
parseStructureCommand(data->structure.chars + startIndex, &data->customValues);
if(instance.config.stat)
{
ms = ffTimeGetTick() - ms;
if (resultDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
}
else
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
if(instance.config.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
#if defined(_WIN32)
if (!instance.config.noBuffer) fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
}
+17
View File
@@ -5,7 +5,24 @@
#include "fastfetch.h"
typedef struct FFCustomValue
{
bool printKey;
FFstrbuf key;
FFstrbuf value;
} FFCustomValue;
// Things only needed by fastfetch
typedef struct FFdata
{
FFstrbuf structure;
FFlist customValues; // List of FFCustomValue
bool loadUserConfig;
} FFdata;
bool ffParseModuleCommand(const char* type);
bool ffParseModuleOptions(const char* key, const char* value);
void ffPrepareCommandOption(FFdata* data);
void ffPrintCommandOption(FFdata* data);
#endif
+2 -2
View File
@@ -12,6 +12,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT)
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT64)
ffStrbufAppendF(buffer, "%" PRIu64, *(uint64_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16)
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8)
@@ -254,7 +256,5 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
}
ffStrbufTrimRight(buffer, ' ');
ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET);
}
+1
View File
@@ -7,6 +7,7 @@ typedef enum FFformatargtype
{
FF_FORMAT_ARG_TYPE_NULL = 0,
FF_FORMAT_ARG_TYPE_UINT,
FF_FORMAT_ARG_TYPE_UINT64,
FF_FORMAT_ARG_TYPE_UINT16,
FF_FORMAT_ARG_TYPE_UINT8,
FF_FORMAT_ARG_TYPE_INT,
+13 -4
View File
@@ -27,6 +27,7 @@ static void initState(FFstate* state)
ffPlatformInit(&state->platform);
state->configDoc = NULL;
state->resultDoc = NULL;
}
static void defaultConfig(void)
@@ -92,6 +93,7 @@ static void defaultConfig(void)
ffInitDEOptions(&instance.config.de);
ffInitDateTimeOptions(&instance.config.dateTime);
ffInitDiskOptions(&instance.config.disk);
ffInitDiskIOOptions(&instance.config.diskIo);
ffInitDisplayOptions(&instance.config.display);
ffInitFontOptions(&instance.config.font);
ffInitGPUOptions(&instance.config.gpu);
@@ -105,6 +107,7 @@ static void defaultConfig(void)
ffInitMediaOptions(&instance.config.media);
ffInitMemoryOptions(&instance.config.memory);
ffInitMonitorOptions(&instance.config.monitor);
ffInitNetIOOptions(&instance.config.netIo);
ffInitOSOptions(&instance.config.os);
ffInitOpenCLOptions(&instance.config.openCL);
ffInitOpenGLOptions(&instance.config.openGL);
@@ -234,11 +237,11 @@ void ffStart(void)
startDetectionThreads();
#endif
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe;
ffHideCursor = instance.config.hideCursor && !instance.config.pipe;
ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc;
ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc;
#ifdef _WIN32
if (!instance.config.noBuffer) setvbuf(stdout, NULL, _IOFBF, 4096);
setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096);
SetConsoleCtrlHandler(consoleHandler, TRUE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode = 0;
@@ -254,7 +257,7 @@ void ffStart(void)
#endif
//reset everything to default before we start printing
if(!instance.config.pipe)
if(!instance.config.pipe && !instance.state.resultDoc)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
if(ffHideCursor)
@@ -305,6 +308,7 @@ static void destroyConfig(void)
ffDestroyDEOptions(&instance.config.de);
ffDestroyDateTimeOptions(&instance.config.dateTime);
ffDestroyDiskOptions(&instance.config.disk);
ffDestroyDiskIOOptions(&instance.config.diskIo);
ffDestroyDisplayOptions(&instance.config.display);
ffDestroyFontOptions(&instance.config.font);
ffDestroyGPUOptions(&instance.config.gpu);
@@ -318,6 +322,7 @@ static void destroyConfig(void)
ffDestroyMediaOptions(&instance.config.media);
ffDestroyMemoryOptions(&instance.config.memory);
ffDestroyMonitorOptions(&instance.config.monitor);
ffDestroyNetIOOptions(&instance.config.netIo);
ffDestroyOSOptions(&instance.config.os);
ffDestroyOpenCLOptions(&instance.config.openCL);
ffDestroyOpenGLOptions(&instance.config.openGL);
@@ -375,6 +380,7 @@ static void destroyState(void)
{
ffPlatformDestroy(&instance.state.platform);
yyjson_doc_free(instance.state.configDoc);
yyjson_mut_doc_free(instance.state.resultDoc);
}
void ffDestroyInstance(void)
@@ -465,6 +471,9 @@ void ffListFeatures(void)
#ifdef FF_HAVE_DDCUTIL
"libddcutil\n"
#endif
#ifdef FF_HAVE_DIRECTX_HEADERS
"Directx Headers\n"
#endif
""
, stdout);
}
+24
View File
@@ -12,6 +12,7 @@
typedef HANDLE FFNativeFD;
#else
#include <unistd.h>
#include <dirent.h>
typedef int FFNativeFD;
#endif
@@ -84,6 +85,8 @@ typedef enum FFPathType
bool ffPathExists(const char* path, FFPathType pathType);
bool ffPathExpandEnv(const char* in, FFstrbuf* out);
#define FF_IO_TERM_RESP_WAIT_MS 100 // #554
FF_C_SCANF(2, 3)
const char* ffGetTerminalResponse(const char* request, const char* format, ...);
@@ -130,4 +133,25 @@ static inline bool wrapFclose(FILE** pfile)
}
#define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose)))
#ifndef _WIN32
static inline bool wrapClosedir(DIR** pdir)
{
assert(pdir);
if (!*pdir)
return false;
closedir(*pdir);
return true;
}
#else
static inline bool wrapClosedir(HANDLE* pdir)
{
assert(pdir);
if (!*pdir)
return false;
FindClose(*pdir);
return true;
}
#endif
#define FF_AUTO_CLOSE_DIR __attribute__((__cleanup__(wrapClosedir)))
#endif // FF_INCLUDED_common_io_io
+5 -9
View File
@@ -54,24 +54,20 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer)
uint32_t free = ffStrbufGetFree(buffer);
while(
(readed = read(fd, buffer->chars + buffer->length, free)) > 0 &&
(uint32_t) readed == free
(readed = read(fd, buffer->chars + buffer->length, free)) > 0
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
if((uint32_t) readed == free)
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
// In case of failure, read returns -1. We don't want to substract the length of the buffer.
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
ffStrbufTrimRight(buffer, ' ');
return readed >= 0;
return buffer->length > 0;
}
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
@@ -150,7 +146,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
fflush(stdout);
//Give the terminal 35ms to respond
if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, 35) <= 0)
if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return "poll() timeout or failed";
+4 -6
View File
@@ -44,16 +44,14 @@ bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer)
bool success;
while(
(success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) &&
(uint32_t) readed == free
readed > 0
) {
buffer->length += (uint32_t) readed;
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
if((uint32_t) readed == free)
ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte.
free = ffStrbufGetFree(buffer);
}
if(readed > 0)
buffer->length += (uint32_t) readed;
buffer->chars[buffer->length] = '\0';
ffStrbufTrimRight(buffer, '\n');
@@ -173,7 +171,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
while (true)
{
if (WaitForSingleObjectEx(hInput, 35, TRUE) != WAIT_OBJECT_0)
if (WaitForSingleObjectEx(hInput, FF_IO_TERM_RESP_WAIT_MS, TRUE) != WAIT_OBJECT_0)
{
SetConsoleMode(hInput, prev_mode);
return "WaitForSingleObject() failed or timeout";
+49 -7
View File
@@ -70,6 +70,20 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p
return "Invalid enum value type; must be a string or integer";
}
static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo)
{
yyjson_mut_doc* doc = instance.state.resultDoc;
if (__builtin_expect(!doc, true)) return NULL;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJson)
baseInfo->generateJson(baseInfo, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
return module;
}
static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
{
if(!isalpha(type[0])) return false;
@@ -80,7 +94,8 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal)
if (ffStrEqualsIgnCase(type, baseInfo->name))
{
if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal);
baseInfo->printModule(baseInfo);
if (!genJson(baseInfo))
baseInfo->printModule(baseInfo);
return true;
}
}
@@ -97,6 +112,22 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
ffPrepareCPUUsage();
break;
}
case 'd': case 'D': {
if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME))
{
if (module) ffParseDiskIOJsonObject(&cfg->diskIo, module);
ffPrepareDiskIO(&cfg->diskIo);
}
break;
}
case 'n': case 'N': {
if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME))
{
if (module) ffParseNetIOJsonObject(&cfg->netIo, module);
ffPrepareNetIO(&cfg->netIo);
}
break;
}
case 'p': case 'P': {
if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME))
{
@@ -128,6 +159,8 @@ static const char* printJsonConfig(bool prepare)
if (!modules) return NULL;
if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects";
yyjson_mut_doc* resultDoc = instance.state.resultDoc;
yyjson_val* item;
size_t idx, max;
yyjson_arr_foreach(modules, idx, max, item)
@@ -157,16 +190,25 @@ static const char* printJsonConfig(bool prepare)
if(!prepare && instance.config.stat)
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms);
if(instance.config.pipe)
puts(str);
ms = ffTimeGetTick() - ms;
if (resultDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root);
yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms);
}
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
{
char str[32];
int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms);
if(instance.config.pipe)
puts(str);
else
printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
#if defined(_WIN32)
if (!instance.config.noBuffer) fflush(stdout);
if (!instance.config.noBuffer && !resultDoc) fflush(stdout);
#endif
}
+13
View File
@@ -8,3 +8,16 @@ void ffPrintJsonConfig(bool prepare);
const char* ffParseGeneralJsonConfig(void);
const char* ffParseDisplayJsonConfig(void);
const char* ffParseLibraryJsonConfig(void);
yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const char *_key,
const FFstrbuf* buf) {
return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length);
}
yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc,
yyjson_mut_val *obj,
const FFstrbuf* buf) {
return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length);
}
+2
View File
@@ -30,6 +30,7 @@ static FFModuleBaseInfo* D[] = {
(void*) &instance.config.de,
(void*) &instance.config.display,
(void*) &instance.config.disk,
(void*) &instance.config.diskIo,
NULL,
};
@@ -82,6 +83,7 @@ static FFModuleBaseInfo* M[] = {
};
static FFModuleBaseInfo* N[] = {
(void*) &instance.config.netIo,
NULL,
};
+30
View File
@@ -0,0 +1,30 @@
#include "netif.h"
#ifndef _WIN32
#include <net/if.h>
#else
#define IF_NAMESIZE 16
#endif
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex);
enum { IF_INDEX_UNINITIALIZED = (uint32_t) -1, IF_INDEX_INVALID = (uint32_t) -2 };
static uint32_t ifIndex = IF_INDEX_UNINITIALIZED;
static char ifName[IF_NAMESIZE + 1];
static inline void init()
{
if (ifIndex == (uint32_t) IF_INDEX_UNINITIALIZED && !ffNetifGetDefaultRouteImpl(ifName, &ifIndex))
ifIndex = (uint32_t) IF_INDEX_INVALID;
}
const char* ffNetifGetDefaultRouteIfName()
{
init();
return ifName;
}
uint32_t ffNetifGetDefaultRouteIfIndex()
{
init();
return ifIndex;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "fastfetch.h"
#ifndef _WIN32
const char* ffNetifGetDefaultRouteIfName();
#endif
uint32_t ffNetifGetDefaultRouteIfIndex();
+98
View File
@@ -0,0 +1,98 @@
#include "netif.h"
#include "common/io/io.h"
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
#if defined(__APPLE__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__NetBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
#elif defined(__FreeBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__OpenBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#else
# error unknown platform
#endif
static struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
for (int i = 0; i < RTAX_MAX; i++)
{
if (rtm->rtm_addrs & (1 << i))
{
if ((1 <<i ) == desired)
return sa;
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
}
}
return NULL;
}
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (pfRoute < 0)
return false;
{
struct timeval timeout = {1, 0};
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
}
int pid = getpid();
struct {
struct rt_msghdr hdr;
struct sockaddr_in dst;
uint8_t data[512];
} rtmsg = {
.hdr = {
.rtm_type = RTM_GET,
.rtm_flags = RTF_UP | RTF_GATEWAY,
.rtm_version = RTM_VERSION,
.rtm_addrs = RTA_DST | RTA_IFP,
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
.rtm_pid = pid,
.rtm_seq = 1,
},
.dst = {
.sin_family = AF_INET,
.sin_len = sizeof(rtmsg.dst),
},
};
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
return false;
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
{
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
{
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
if (sdl)
{
assert(sdl->sdl_nlen <= IF_NAMESIZE);
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
iface[sdl->sdl_nlen] = '\0';
*ifIndex = sdl->sdl_index;
return true;
}
return false;
}
}
return false;
}
+28
View File
@@ -0,0 +1,28 @@
#include "netif.h"
#include "common/io/io.h"
#include <net/if.h>
#include <stdio.h>
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
if (!netRoute) return false;
// skip first line
flockfile(netRoute);
while (getc_unlocked(netRoute) != '\n');
funlockfile(netRoute);
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2)
{
if (destination != 0) continue;
*ifIndex = if_nametoindex(iface);
return true;
}
return false;
}
+27
View File
@@ -0,0 +1,27 @@
#include "netif.h"
#include "util/mallocHelper.h"
#include <iphlpapi.h>
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char* iface/* unsupported */, uint32_t* ifIndex)
{
ULONG size = 0;
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
return false;
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
return false;
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
{
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
{
*ifIndex = ipForwardRow->dwForwardIfIndex;
break;
}
}
return true;
}
+4 -3
View File
@@ -77,7 +77,8 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con
bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout)
{
#ifdef FF_HAVE_THREADS
ffThreadJoin(state->thread);
if (!ffThreadJoin(state->thread, timeout))
return false;
#endif
if(state->sockfd == -1)
return false;
@@ -85,8 +86,8 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui
if(timeout > 0)
{
struct timeval timev;
timev.tv_sec = 0;
timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds
timev.tv_sec = timeout / 1000;
timev.tv_usec = (__typeof__(timev.tv_usec)) ((timeout % 1000) * 1000); //milliseconds to microseconds
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
}
+13 -1
View File
@@ -3,14 +3,22 @@
#include "util/FFstrbuf.h"
struct yyjson_val;
struct yyjson_mut_doc;
struct yyjson_mut_val;
// Must be the first field of FFModuleOptions
typedef struct FFModuleBaseInfo
{
const char* name;
// A dirty polymorphic implementation in C.
// This is UB, because `void*` is not compatible with `FF*Options*`.
// However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer
// https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type
bool (*parseCommandOptions)(void* options, const char* key, const char* value);
void (*parseJsonObject)(void* options, struct yyjson_val *module);
void (*printModule)(void* options);
void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
void (*printHelpFormat)(void);
} FFModuleBaseInfo;
static inline void ffOptionInitModuleBaseInfo(
@@ -18,13 +26,17 @@ static inline void ffOptionInitModuleBaseInfo(
const char* name,
void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value)
void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module)
void* printModule // void (*const printModule)(void* options)
void* printModule, // void (*const printModule)(void* options)
void* generateJson, // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
void (*printHelpFormat)(void)
)
{
baseInfo->name = name;
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson;
baseInfo->printHelpFormat = printHelpFormat;
}
typedef struct FFModuleArgs
+20 -3
View File
@@ -10,6 +10,10 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
if(moduleName == NULL)
return;
//This is used as a magic value for hiding keys
if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " "))
return;
if(!instance.config.pipe)
{
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
@@ -112,9 +116,7 @@ void ffPrintColor(const FFstrbuf* colorValue)
if(colorValue->length == 0)
return;
fputs("\033[", stdout);
ffStrbufWriteTo(colorValue, stdout);
fputc('m', stdout);
printf("\e[%sm", colorValue->chars);
}
void ffPrintCharTimes(char c, uint32_t times)
@@ -130,3 +132,18 @@ void ffPrintCharTimes(char c, uint32_t times)
if(remaining > 0)
fwrite(str, 1, remaining, stdout);
}
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[])
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(name);
ffStrbufLowerCase(&buffer);
printf("--%s-format:\n", buffer.chars);
printf("Sets the format string for %s output.\n", name);
puts("To see how a format string is constructed, take a look at \"fastfetch --help format\".");
puts("The following values are passed:");
for(unsigned i = 0; i < numArgs; i++)
printf(" {%u}: %s\n", i + 1, args[i]);
printf("The default is something similar to \"%s\".\n", def);
}
+2
View File
@@ -25,4 +25,6 @@ FF_C_PRINTF(4, 5) void ffPrintError(const char* moduleName, uint8_t moduleIndex,
void ffPrintColor(const FFstrbuf* colorValue);
void ffPrintCharTimes(char c, uint32_t times);
void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]);
#endif
+1
View File
@@ -38,6 +38,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
close(pipes[0]);
close(pipes[1]);
close(useStdErr ? STDOUT_FILENO : STDERR_FILENO);
setenv("LANG", "C", 1);
execvp(argv[0], argv);
exit(901);
}
+38 -2
View File
@@ -10,6 +10,7 @@
#include <handleapi.h>
#include <synchapi.h>
#include <process.h>
#include <processthreadsapi.h>
#define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT
typedef SRWLOCK FFThreadMutex;
typedef HANDLE FFThreadType;
@@ -21,9 +22,23 @@
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; }
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static __stdcall unsigned fn ## ThreadMain () { fn(); return 0; }
static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); }
static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, 0xffffffff /*INFINITE*/); }
static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout)
{
if (WaitForSingleObject(thread, timeout == 0 ? (DWORD) -1 : timeout) != 0 /*WAIT_OBJECT_0*/)
{
TerminateThread(thread, (DWORD) -1);
CloseHandle(thread);
return false;
}
CloseHandle(thread);
return true;
}
#else
#include <pthread.h>
#include <signal.h>
#if __has_include(<pthread_np.h>)
#include <pthread_np.h>
#endif
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t FFThreadMutex;
typedef pthread_t FFThreadType;
@@ -37,7 +52,28 @@
#define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; }
#define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static void* fn ## ThreadMain () { fn(); return NULL; }
static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); }
static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); }
static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout)
{
#if (defined(__linux__) && !defined(__ANDROID__)) || __has_include(<pthread_np.h>)
if (timeout > 0)
{
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
{
ts.tv_sec += ts.tv_sec / 1000;
ts.tv_nsec += (ts.tv_nsec % 1000) * 1000000;
if (pthread_timedjoin_np(thread, NULL, &ts) != 0)
{
pthread_kill(thread, SIGTERM);
return false;
}
return true;
}
}
#endif
pthread_join(thread, NULL);
return true;
}
#endif
#else //FF_HAVE_THREADS
#define FF_THREAD_MUTEX_INITIALIZER 0
+14
View File
@@ -7,6 +7,7 @@
#ifdef _WIN32
#include <synchapi.h>
#include <profileapi.h>
#include <sysinfoapi.h>
#else
#include <time.h>
#endif
@@ -26,6 +27,19 @@ static inline uint64_t ffTimeGetTick() //In msec
#endif
}
static inline uint64_t ffTimeGetNow()
{
#ifdef _WIN32
uint64_t timeNow;
GetSystemTimeAsFileTime((FILETIME*) &timeNow);
return (timeNow - 116444736000000000ull) / 10000ull;
#else
struct timespec timeNow;
clock_gettime(CLOCK_REALTIME, &timeNow);
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000));
#endif
}
static inline void ffTimeSleep(uint32_t msec)
{
#ifdef _WIN32
+8 -3
View File
@@ -360,7 +360,7 @@
#--terminal-key Terminal
#--terminalfont-key Terminal Font
#--cpu-key CPU
#--cpu-usage-key CPU Usage
#--cpuusage-key CPU Usage
#--gpu-key GPU {1}
#--memory-key Memory
#--swap-key Swap
@@ -370,6 +370,7 @@
#--lm-key LM
#--locale-key Locale
#--localip-key Local IP ({1})
#--netio-key Network IO ({1})
#--publicip-key Public IP
#--wifi-key Wifi
#--weather-key Weather
@@ -391,6 +392,7 @@
# For information on format strings, see "fastfetch --help format".
# To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format".
# An empty format string (As they are currently below) will behave as if it was not set.
#--title-format
#--os-format
#--host-format
#--chassis-format
@@ -411,7 +413,7 @@
#--terminal-format
#--terminalfont-format
#--cpu-format
#--cpu-usage-format
#--cpuusage-format
#--gpu-format
#--memory-format
#--swap-format
@@ -421,6 +423,7 @@
#--lm-format
#--locale-format
#--localip-format
#--netio-format
#--publicip-format
#--weather-format
#--monitor-format
@@ -439,6 +442,7 @@
# Key color options:
# Overrides the global `--color-keys` for one specified module
#--title-key-color
#--os-key-color
#--host-key-color
#--chassis-key-color
@@ -459,7 +463,7 @@
#--terminal-key-color
#--terminalfont-key-color
#--cpu-key-color
#--cpu-usage-key-color
#--cpuusage-key-color
#--gpu-key-color
#--memory-key-color
#--swap-key-color
@@ -469,6 +473,7 @@
#--lm-key-color
#--locale-key-color
#--localip-key-color
#--netio-key-color
#--publicip-key-color
#--weather-key-color
#--monitor-key-color
+14 -6
View File
@@ -129,25 +129,33 @@ Module specific options:
--disk-show-external <?value>: Set if external volume should be printed. Default is true
--disk-show-hidden <?value>: Set if hidden volumes should be printed. Default is false
--disk-show-subvolumes <?value>: Set if subvolumes should be printed. Default is false
--disk-show-readonly <?value>: Set if read only volumes should be printed. Default is false
--disk-show-unknown <?value>: Set if unknown (unable to detect sizes) volumes should be printed. Default is false
--disk-use-available <?value>: Use f_bavail (lpFreeBytesAvailableToCaller for Windows) instead of f_bfree to calculate used bytes. Default is false
--diskio-name-prefix <str>: Show disks with given name prefix only. Default is empty
--bluetooth-show-disconnected: <?value>: Set if disconnected bluetooth devices should be printed. Default is false
--display-compact-type: <?string>: Set if all displays should be printed in one line. Default is none
--display-detect-name: <?value>: Set if display name should be detected and printed (if supported). Default is false
--display-precise-refresh-rate: <?value>:Set if decimal refresh rates should not be rounded into integers when printing. Default is true
--brightness-ddcci-sleep: <num> Set the sleep times (in ms) when sending DDC/CI requests. See <https://www.ddcutil.com/performance_options/#option-sleep-multiplier> for detail. Default is 10
--sound-type: <value>: Set what type of sound devices should be printed. Should be either main, active or all. Default is main
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
--cpu-freq-ndigits <num>: Set the number of digits to keep after the decimal point when printing CPU frequency. Default is 2
--cpuusage-separate <?value>: Display CPU usage per CPU logical core, instead of an average result. Default is false
--gpu-temp <?value>: Detect and display GPU temperature if supported. Default is false
--gpu-force-vulkan <?value>: Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`. Default is false
--gpu-hide-type <?value>: Specify the type of GPUs should not be printed. Must be `integrated`, `discrete` or `none`. Default is none
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--battery-temp <?value>: Detect and display Battery temperature if supported. Default is false
--localip-show-ipv4 <?value>: Show IPv4 addresses in local ip module. Default is true
--localip-show-ipv6 <?value>: Show IPv6 addresses in local ip module. Default is false
--localip-show-mac <?value>: Show mac addresses in local ip module. Default is false
--localip-show-loop <?value>: Show loop back addresses (127.0.0.1) in local ip module. Default is false
--localip-name-prefix <str>: Show IPs with given name prefix only. Default is empty
--localip-default-route-only <?value>: Show ips that are used for default routing only. Default is false
--localip-name-prefix <str>: Show interfaces with given interface name prefix only. Default is empty
--localip-default-route-only <?value>: Show the interface that is used for default routing only. Default is false
--localip-compact <?value>: Show all IPs in one line. Default is false
--netio-name-prefix <str>: Show interfaces with given name prefix only. Default is empty
--netio-default-route-only <?value>: Show the interfac that is used for default routing only. Default is false
--publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0)
--publicip-url: The URL of public IP detection server to be used.
--weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`).
+2 -2
View File
@@ -7,7 +7,7 @@
#define FF_BATTERY_TEMP_UNSET (0/0.0)
typedef struct BatteryResult
typedef struct FFBatteryResult
{
FFstrbuf manufacturer;
FFstrbuf modelName;
@@ -15,7 +15,7 @@ typedef struct BatteryResult
double capacity;
FFstrbuf status;
double temperature;
} BatteryResult;
} FFBatteryResult;
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
+3 -3
View File
@@ -33,7 +33,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
if (!yyjson_is_obj(root))
return "Battery info result is not a JSON object";
BatteryResult* battery = ffListAdd(results);
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
@@ -68,7 +68,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
return NULL;
ffStrbufClear(&temp);
BatteryResult* battery = ffListAdd(results);
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
@@ -78,7 +78,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
ffStrbufAppendS(&battery->status, "AC powered");
ffStrbufClear(&temp);
if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true"))
{
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
+2 -6
View File
@@ -17,12 +17,8 @@ static double detectBatteryTemp(void)
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
{
CFMutableDictionaryRef matchDict = IOServiceMatching("AppleSmartBattery");
if (matchDict == NULL)
return "IOServiceMatching(\"AppleSmartBattery\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleSmartBattery"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
@@ -38,7 +34,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
bool boolValue;
const char* error;
BatteryResult* battery = ffListAdd(results);
FFBatteryResult* battery = ffListAdd(results);
battery->capacity = 0.0/0.0;
int currentCapacity, maxCapacity;
+1 -1
View File
@@ -32,7 +32,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT))
continue;
BatteryResult* battery = ffListAdd(results);
FFBatteryResult* battery = ffListAdd(results);
battery->temperature = FF_BATTERY_TEMP_UNSET;
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->modelName);
+1 -1
View File
@@ -27,7 +27,7 @@ static void parseBattery(FFstrbuf* dir, FFlist* results)
if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0)
return;
BatteryResult* result = ffListAdd(results);
FFBatteryResult* result = ffListAdd(results);
//capacity must exist and be not empty
ffStrbufAppendS(dir, "/capacity");
+2 -2
View File
@@ -74,7 +74,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY))
continue;
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
if(memcmp(bi.Chemistry, "PbAc", 4) == 0)
ffStrbufInitS(&battery->technology, "Lead Acid");
@@ -143,7 +143,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
SYSTEM_BATTERY_STATE info;
if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->modelName);
ffStrbufInit(&battery->manufacturer);
ffStrbufInit(&battery->technology);
+3 -3
View File
@@ -5,15 +5,15 @@
#include "fastfetch.h"
typedef struct FFBluetoothDevice
typedef struct FFBluetoothResult
{
FFstrbuf name;
FFstrbuf address;
FFstrbuf type;
uint8_t battery; // 0-100%
bool connected;
} FFBluetoothDevice;
} FFBluetoothResult;
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */);
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
#endif
+2 -2
View File
@@ -2,7 +2,7 @@
#import <IOBluetooth/IOBluetooth.h>
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
{
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
if(!ioDevices)
@@ -10,7 +10,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
for(IOBluetoothDevice* ioDevice in ioDevices)
{
FFBluetoothDevice* device = ffListAdd(devices);
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
ffStrbufInit(&device->type);
+4 -4
View File
@@ -44,7 +44,7 @@ array [ //root
]
*/
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
@@ -72,7 +72,7 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
ffDBusGetBool(dbus, &dictIter, &device->connected);
}
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
{
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
return;
@@ -130,7 +130,7 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
DBusMessageIter arrayIter;
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
FFBluetoothDevice* device = ffListAdd(devices);
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
@@ -193,7 +193,7 @@ static const char* detectBluetooth(FFlist* devices)
#endif
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */)
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
return detectBluetooth(devices);
@@ -1,6 +1,6 @@
#include "bluetooth.h"
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */)
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
return "Not supported on this platform";
}
+10 -5
View File
@@ -7,7 +7,7 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-sign"
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
{
BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = {
.fReturnConnected = TRUE,
@@ -25,7 +25,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
return "BluetoothFindFirstDevice() failed or no devices found";
do {
FFBluetoothDevice* device = ffListAdd(devices);
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInit(&device->name);
ffStrbufInit(&device->address);
ffStrbufInit(&device->type);
@@ -33,9 +33,14 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */)
device->connected = !!btdi.fConnected;
ffStrbufSetWS(&device->name, btdi.szName);
for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i)
ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]);
ffStrbufTrimRight(&device->name, ':');
ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
btdi.Address.rgBytes[0],
btdi.Address.rgBytes[1],
btdi.Address.rgBytes[2],
btdi.Address.rgBytes[3],
btdi.Address.rgBytes[4],
btdi.Address.rgBytes[5]);
//https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf
if(BitTest(&btdi.ulClassofDevice, 13))
+2 -2
View File
@@ -9,9 +9,9 @@
typedef struct FFBrightnessResult
{
FFstrbuf name;
float value;
double min, max, current;
} FFBrightnessResult;
const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result); // list of FFBrightnessResult
#endif
+96 -14
View File
@@ -1,9 +1,27 @@
#include "brightness.h"
#include "detection/displayserver/displayserver.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/ddcci.h"
#include "util/edidHelper.h"
#include <CoreGraphics/CoreGraphics.h>
// DDC/CI
#ifdef __aarch64__
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import));
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import));
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import));
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import));
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
#else
// DDC/CI (Intel)
#include <IOKit/IOKitLib.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <IOKit/i2c/IOI2CInterface.h>
extern void CGSServiceForDisplayNumber(CGDirectDisplayID display, io_service_t* service) __attribute__((weak_import));
#endif
// ACPI
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
// Works for internal display
@@ -20,7 +38,9 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess)
{
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = value * 100;
brightness->current = value;
brightness->max = 1;
brightness->min = 0;
ffStrbufInitCopy(&brightness->name, &display->name);
}
}
@@ -29,19 +49,16 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
return NULL;
}
#ifdef __aarch64__
// https://github.com/waydabber/m1ddc
// Works for Apple Silicon and USB-C adapter connection ( but not HTMI )
FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy");
if (matchDict == NULL)
return "IOServiceMatching(\"DCPAVServiceProxy\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("DCPAVServiceProxy"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
@@ -76,7 +93,7 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
for (uint32_t i = 0; i < 2; ++i)
{
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn));
usleep(10000);
usleep(options->ddcciSleep * 1000);
}
}
@@ -90,7 +107,9 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = (float) current * 100.f / max;
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInit(&brightness->name);
uint8_t edid[128] = {};
@@ -101,17 +120,80 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result)
return NULL;
}
#else
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFBrightnessOptions* options, FFlist* result)
{
if (!CGSServiceForDisplayNumber) return "CGSServiceForDisplayNumber is not available";
const char* ffDetectBrightness(FFlist* result)
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_EXTERNAL)
{
io_service_t framebuffer = 0;
CGSServiceForDisplayNumber((CGDirectDisplayID)display->id, &framebuffer);
if (framebuffer == 0) continue;
IOItemCount count;
if (IOFBGetI2CInterfaceCount(framebuffer, &count) != KERN_SUCCESS || count == 0) continue;
io_service_t interface = 0;
if (IOFBCopyI2CInterfaceForBus(framebuffer, 0, &interface) != KERN_SUCCESS) continue;
uint8_t i2cOut[12] = {};
IOI2CConnectRef connect;
if (IOI2CInterfaceOpen(interface, kNilOptions, &connect) != KERN_SUCCESS)
{
IOObjectRelease(interface);
continue;
}
uint8_t i2cIn[] = { 0x51, 0x82, 0x01, 0x10 /* luminance */, 0 };
i2cIn[4] = 0x6E ^ i2cIn[0] ^ i2cIn[1] ^ i2cIn[2] ^ i2cIn[3];
IOI2CRequest request = {
.commFlags = kNilOptions,
.sendAddress = 0x6e,
.sendTransactionType = kIOI2CSimpleTransactionType,
.sendBuffer = (vm_address_t) i2cIn,
.sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]),
.minReplyDelay = options->ddcciSleep,
.replyAddress = 0x6F,
.replySubAddress = 0x51,
.replyTransactionType = kIOI2CDDCciReplyTransactionType,
.replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]),
.replyBuffer = (vm_address_t) i2cOut,
};
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
IOI2CInterfaceClose(connect, kNilOptions);
IOObjectRelease(interface);
if (ret != KERN_SUCCESS || request.result != kIOReturnSuccess) continue;
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue;
uint32_t current = ((uint32_t) i2cOut[8] << 8u) + (uint32_t) i2cOut[9];
uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7];
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInitCopy(&brightness->name, &display->name);
}
}
return NULL;
}
#endif
const char* ffDetectBrightness(FFBrightnessOptions* options, FFlist* result)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
detectWithDisplayServices(displayServer, result);
#ifdef __aarch64__
if (displayServer->displays.length > result->length)
detectWithDdcci(result);
#endif
detectWithDdcci(displayServer, options, result);
return NULL;
}
+10 -7
View File
@@ -9,7 +9,7 @@
#include <sys/fcntl.h>
#include <unistd.h>
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
// https://man.freebsd.org/cgi/man.cgi?query=backlight&sektion=9
char path[] = "/dev/backlight/backlight0";
@@ -26,22 +26,25 @@ const char* ffDetectBrightness(FFlist* result)
if(ioctl(blfd, BACKLIGHTGETSTATUS, &status) < 0)
continue;
FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInit(&display->name);
display->value = (float) status.brightness / BACKLIGHTMAXLEVELS;
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
ffStrbufInit(&brightness->name);
brightness->max = BACKLIGHTMAXLEVELS;
brightness->min = 0;
brightness->current = status.brightness;
struct backlight_info info;
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
ffStrbufAppendS(&display->name, info.name);
ffStrbufAppendS(&brightness->name, info.name);
}
return NULL;
}
#else
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
return "Backlight is supported only on FreeBSD 13 and newer";
}
#endif
#endif
+13 -7
View File
@@ -72,8 +72,9 @@ static const char* detectWithBacklight(FFlist* result)
}
else
ffStrbufInitS(&brightness->name, entry->d_name);
double maxBrightness = ffStrbufToDouble(&buffer);
brightness->value = (float) (actualBrightness * 100 / maxBrightness);
brightness->max = ffStrbufToDouble(&buffer);
brightness->min = 0;
brightness->current = actualBrightness;
}
}
ffStrbufSubstrBefore(&backlightDir, backlightDirLength);
@@ -91,16 +92,19 @@ static const char* detectWithBacklight(FFlist* result)
#include <ddcutil_c_api.h>
static const char* detectWithDdcci(FFlist* result)
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
{
FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD(libddcutil, &instance.config.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_display_info_list2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_open_display2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_get_any_vcp_value_using_explicit_type)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_free_any_vcp_value)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_close_display)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libddcutil, ddca_set_default_sleep_multiplier)
libddcutil = NULL; // Don't dlclose libddcutil. See https://github.com/rockowitz/ddcutil/issues/330
ffddca_set_default_sleep_multiplier(options->ddcciSleep / 40.0);
FF_AUTO_FREE DDCA_Display_Info_List* infoList = NULL;
if (__builtin_expect(ffddca_get_display_info_list2(false, &infoList) < 0, 0))
return "ddca_get_display_info_list2(false, &infoList) failed";
@@ -123,7 +127,9 @@ static const char* detectWithDdcci(FFlist* result)
ffddca_free_any_vcp_value(vcpValue);
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = (float) current * 100.f / (float) max;
brightness->max = max;
brightness->min = 0;
brightness->current = current;
ffStrbufInitS(&brightness->name, display->model_name);
}
ffddca_close_display(handle);
@@ -134,14 +140,14 @@ static const char* detectWithDdcci(FFlist* result)
}
#endif
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
detectWithBacklight(result);
#ifdef FF_HAVE_DDCUTIL
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
if (result->length < displayServer->displays.length)
detectWithDdcci(result);
detectWithDdcci(options, result);
#endif
return NULL;
@@ -1,6 +1,6 @@
#include "brightness.h"
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FF_MAYBE_UNUSED FFlist* result)
{
return "Not supported on this platform";
}
@@ -20,7 +20,9 @@ static const char* detectWithWmi(FFlist* result)
if(FFWmiVariant vtValue = record.get(L"CurrentBrightness"))
{
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = vtValue.get<uint8_t>();
brightness->max = 100;
brightness->min = 0;
brightness->current = vtValue.get<uint8_t>();
ffStrbufInit(&brightness->name);
if (FFWmiVariant vtName = record.get(L"InstanceName"))
@@ -51,7 +53,9 @@ static char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist*
else
ffStrbufInitWS(&brightness->name, physicalMonitor.szPhysicalMonitorDescription);
brightness->value = (float) (curr - min) * 100.f / (float) (max - min);
brightness->max = max;
brightness->min = min;
brightness->current = curr;
}
}
}
@@ -69,7 +73,7 @@ static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer)
}
extern "C"
const char* ffDetectBrightness(FFlist* result)
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
+1 -1
View File
@@ -25,7 +25,7 @@ const char* ffDetectChassis(FFChassisResult* result)
if(result->type.length)
{
const char* typeStr = ffChassisTypeToString(ffStrbufToUInt16(&result->type, 9999));
const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999));
if(typeStr)
ffStrbufSetS(&result->type, typeStr);
}
+71 -15
View File
@@ -2,17 +2,6 @@
#include "common/sysctl.h"
#include "detection/temps/temps_apple.h"
static double getFrequency(const char* propName)
{
double herz = (double) ffSysctlGetInt64(propName, 0);
if(herz <= 0.0)
return herz;
herz /= 1000.0; //to KHz
herz /= 1000.0; //to MHz
return herz / 1000.0; //to GHz
}
static double detectCpuTemp(const FFstrbuf* cpuName)
{
double result = 0;
@@ -31,11 +20,81 @@ static double detectCpuTemp(const FFstrbuf* cpuName)
return result;
}
#ifdef __aarch64__
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
static const char* detectFrequency(FFCPUResult* cpu)
{
// https://github.com/giampaolo/psutil/pull/2222/files
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching("AppleARMIODevice"), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
io_name_t name;
if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS)
continue;
if (strcmp(name, "pmgr") != 0)
continue;
uint32_t pMin, eMin, aMax, pCoreLength;
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore
ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore
cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000);
if (pCoreLength >= 8)
{
ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL);
cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000);
}
else
cpu->frequencyMax = 0.0;
CFRelease(properties);
IOObjectRelease(registryEntry);
}
IOObjectRelease(iterator);
return NULL;
}
#else
static const char* detectFrequency(FFCPUResult* cpu)
{
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
if(cpu->frequencyMax > 0.0)
cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0;
else
{
unsigned current = 0;
size_t size = sizeof(current);
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, &current, &size, NULL, 0) == 0)
cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0;
}
return NULL;
}
#endif
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
return "sysctlbyname(machdep.cpu.brand_string) failed";
ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor);
if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple "))
ffStrbufAppendS(&cpu->vendor, "Apple");
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1);
if(cpu->coresPhysical == 1)
@@ -49,10 +108,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if(cpu->coresOnline == 1)
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
cpu->frequencyMin = getFrequency("hw.cpufrequency_min");
cpu->frequencyMax = getFrequency("hw.cpufrequency_max");
if(cpu->frequencyMax == 0.0)
cpu->frequencyMax = getFrequency("hw.cpufrequency");
detectFrequency(cpu);
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
+4 -1
View File
@@ -16,7 +16,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
ffDetectThermalTemp(&cpu->temperature);
{
if (!ffDetectCpuTemp(&cpu->temperature))
ffDetectThermalTemp(&cpu->temperature);
}
return NULL;
}
+14 -1
View File
@@ -1,5 +1,6 @@
#include "cpu.h"
#include "common/io/io.h"
#include "common/processing.h"
#include "common/properties.h"
#include "detection/temps/temps_linux.h"
#include "util/mallocHelper.h"
@@ -128,7 +129,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
const char* error = parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch);
if (error) return error;
cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1);
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 1);
cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresOnline = (uint16_t) get_nprocs();
@@ -163,5 +164,17 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectAndroid(cpu);
#endif
#ifdef __linux__
if (cpu->name.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL }))
{
ffParsePropLines(buffer.chars, "Model name:", &cpu->name);
if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name);
}
}
#endif
return NULL;
}
+1 -1
View File
@@ -35,7 +35,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed";
}
FF_HKEY_AUTO_DESTROY hKey;
FF_HKEY_AUTO_DESTROY hKey = NULL;
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
+35 -23
View File
@@ -4,42 +4,54 @@
#include <stdint.h>
// We need to use uint64_t because sizeof(long) == 4 on Windows
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
static uint64_t inUseAll1, totalAll1;
static FFlist cpuTimes1;
void ffPrepareCPUUsage(void)
{
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
assert(cpuTimes1.elementSize == 0);
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
ffGetCpuUsageInfo(&cpuTimes1);
}
const char* ffGetCpuUsageResult(double* result)
const char* ffGetCpuUsageResult(FFlist* result)
{
const char* error = NULL;
if(inUseAll1 == 0 && totalAll1 == 0)
if(cpuTimes1.elementSize == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
return error;
ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo));
error = ffGetCpuUsageInfo(&cpuTimes1);
if(error) return error;
ffTimeSleep(200);
}
while(true)
{
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
if(cpuTimes1.length == 0) return "No CPU cores found";
if(inUseAll2 != inUseAll1)
FF_LIST_AUTO_DESTROY cpuTimes2 = ffListCreate(sizeof(FFCpuUsageInfo));
retry:
error = ffGetCpuUsageInfo(&cpuTimes2);
if(error) return error;
if(cpuTimes1.length != cpuTimes2.length) return "Unexpected CPU usage result";
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
if (cpuTime2->totalAll <= cpuTime1->totalAll)
{
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
inUseAll1 = inUseAll2;
totalAll1 = totalAll2;
return NULL;
}
else
ffListClear(&cpuTimes2);
ffTimeSleep(200);
goto retry;
}
}
for (uint32_t i = 0; i < cpuTimes1.length; ++i)
{
FFCpuUsageInfo* cpuTime1 = ffListGet(&cpuTimes1, i);
FFCpuUsageInfo* cpuTime2 = ffListGet(&cpuTimes2, i);
*(double*) ffListAdd(result) = (double)(cpuTime2->inUseAll - cpuTime1->inUseAll) / (double)(cpuTime2->totalAll - cpuTime1->totalAll) * 100;
cpuTime1->inUseAll = cpuTime2->inUseAll;
cpuTime1->totalAll = cpuTime2->totalAll;
}
return NULL;
}
+9 -1
View File
@@ -3,6 +3,14 @@
#ifndef FF_INCLUDED_detection_cpuusage_cpuusage
#define FF_INCLUDED_detection_cpuusage_cpuusage
const char* ffGetCpuUsageResult(double* result);
#include "fastfetch.h"
typedef struct FFCpuUsageInfo {
uint64_t inUseAll;
uint64_t totalAll;
} FFCpuUsageInfo;
const char* ffGetCpuUsageInfo(FFlist* cpuTimes);
const char* ffGetCpuUsageResult(FFlist* result); // list of double
#endif
+20 -11
View File
@@ -4,20 +4,29 @@
#include <mach/processor_info.h>
#include <mach/mach_host.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
host_cpu_load_info_data_t cpustats;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
natural_t numCPUs = 0U;
processor_info_array_t cpuInfo;
mach_msg_type_number_t numCpuInfo;
*inUseAll = *totalAll = 0;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUs, &cpuInfo, &numCpuInfo) != KERN_SUCCESS)
return "host_processor_info() failed";
if (numCPUs * CPU_STATE_MAX != numCpuInfo)
return "Unexpected host_processor_info() result";
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)(&cpustats), &count) != KERN_SUCCESS)
return "host_statistics() failed";
*inUseAll = cpustats.cpu_ticks[CPU_STATE_USER]
+ cpustats.cpu_ticks[CPU_STATE_SYSTEM]
+ cpustats.cpu_ticks[CPU_STATE_NICE];
*totalAll = *inUseAll + cpustats.cpu_ticks[CPU_STATE_IDLE];
for (natural_t i = 0U; i < numCPUs; ++i)
{
integer_t inUse = cpuInfo[CPU_STATE_MAX * i + CPU_STATE_USER]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+26 -9
View File
@@ -1,19 +1,36 @@
#include "detection/cpuusage/cpuusage.h"
#include "util/mallocHelper.h"
#include <sys/types.h>
#include <sys/user.h>
#include <sys/sysctl.h>
#include <sys/resource.h>
#include <stdlib.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
// interrupt processing, user processes, system processing, lock spinning, and idling
uint64_t cpTime[5];
size_t neededLength = sizeof(cpTime);
if(sysctlbyname("kern.cp_time", cpTime, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_time) failed";
size_t neededLength = 0;
if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_times, NULL) failed";
*inUseAll = cpTime[0] + cpTime[1] + cpTime[2] + cpTime[3];
*totalAll = *inUseAll + cpTime[4];
uint32_t coreCount = neededLength / (CPUSTATES * (uint32_t) sizeof(uint64_t));
assert(coreCount > 0);
FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength);
if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0)
return "sysctlbyname(kern.cp_times, cpTime) failed";
for (uint32_t i = 0; i < coreCount; ++i)
{
uint64_t* cpTime = cpTimes[i];
uint64_t inUse = cpTime[CP_USER] + cpTime[CP_NICE] + cpTime[CP_SYS];
uint64_t total = cpTime[CP_INTR] + cpTime[CP_IDLE];
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+16 -11
View File
@@ -1,14 +1,13 @@
#include "fastfetch.h"
#include "detection/cpuusage/cpuusage.h"
#include "common/io/io.h"
#include <stdio.h>
#include <inttypes.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
FILE* procStat = fopen("/proc/stat", "r");
FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r");
if(procStat == NULL)
{
#ifdef __ANDROID__
@@ -17,16 +16,22 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
return "fopen(\"""/proc/stat\", \"r\") == NULL";
#endif
}
// Skip first line
if (fscanf(procStat, "cpu%*[^\n]\n") < 0)
return "fscanf() first line failed";
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7)
{
fclose(procStat);
return "fscanf() failed";
}
*inUseAll = user + nice + system;
*totalAll = *inUseAll + idle + iowait + irq + softirq;
uint64_t inUse = user + nice + system;
uint64_t total = inUse + idle + iowait + irq + softirq;
fclose(procStat);
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
}
+9 -6
View File
@@ -6,7 +6,7 @@
#include <ntstatus.h>
#include <winternl.h>
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
const char* ffGetCpuUsageInfo(FFlist* cpuTimes)
{
ULONG size = 0;
if(NtQuerySystemInformation(SystemProcessorPerformanceInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH)
@@ -16,8 +16,6 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessorPerformanceInformation, pinfo, size, &size)))
return "NtQuerySystemInformation(SystemProcessorPerformanceInformation, size) failed";
*inUseAll = *totalAll = 0;
for (uint32_t i = 0; i < size / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); ++i)
{
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* coreInfo = pinfo + i;
@@ -28,9 +26,14 @@ const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
coreInfo->KernelTime.QuadPart -= coreInfo->IdleTime.QuadPart;
coreInfo->KernelTime.QuadPart += dpcTime + interruptTime;
LONGLONG inUse = coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart;
*inUseAll += (uint64_t)inUse;
*totalAll += (uint64_t)(inUse + coreInfo->IdleTime.QuadPart);
uint64_t inUse = (uint64_t) (coreInfo->UserTime.QuadPart + coreInfo->KernelTime.QuadPart);
uint64_t total = inUse + (uint64_t)coreInfo->IdleTime.QuadPart;
FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes);
*info = (FFCpuUsageInfo) {
.inUseAll = (uint64_t)inUse,
.totalAll = (uint64_t)total,
};
}
return NULL;
-71
View File
@@ -1,71 +0,0 @@
#include "fastfetch.h"
#include "detection/datetime/datetime.h"
#include "common/thread.h"
#include <time.h>
const FFDateTimeResult* ffDetectDateTime(void)
{
static FFDateTimeResult result;
static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER;
static bool init = false;
ffThreadMutexLock(&mutex);
if (init)
{
ffThreadMutexUnlock(&mutex);
return &result;
}
init = true;
const time_t t = time(NULL);
struct tm* tm = localtime(&t);
result.year = (uint16_t) (tm->tm_year + 1900);
result.yearShort = (uint8_t) (result.year % 100);
result.month = (uint8_t) (tm->tm_mon + 1);
ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm);
ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm);
ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm);
result.week = (uint8_t) (tm->tm_yday / 7 + 1);
ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm);
ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm);
result.dayInYear = (uint8_t) (tm->tm_yday + 1);
result.dayInMonth = (uint8_t) tm->tm_mday;
result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday;
result.hour = (uint8_t) tm->tm_hour;
ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm);
result.hour12 = (uint8_t) (result.hour % 12);
ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm);
result.minute = (uint8_t) tm->tm_min;
ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm);
result.second = (uint8_t) tm->tm_sec;
ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC);
result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm);
ffThreadMutexUnlock(&mutex);
return &result;
}
-35
View File
@@ -1,35 +0,0 @@
#pragma once
#ifndef FF_INCLUDED_detection_datetime_datetime
#define FF_INCLUDED_detection_datetime_datetime
#include "fastfetch.h"
typedef struct FFDateTimeResult
{
//Examples for 21.02.2022 - 15:18:37
uint16_t year; //2022
uint8_t yearShort; //22
uint8_t month; //2
FFstrbuf monthPretty; //02
FFstrbuf monthName; //February
FFstrbuf monthNameShort; //Feb
uint8_t week; //8
FFstrbuf weekday; //Monday
FFstrbuf weekdayShort; //Mon
uint16_t dayInYear; //52
uint8_t dayInMonth; //21
uint8_t dayInWeek; //1
uint8_t hour; //15
FFstrbuf hourPretty; //15
uint8_t hour12; //3
FFstrbuf hour12Pretty; //03
uint8_t minute; //18
FFstrbuf minutePretty; //18
uint8_t second; //37
FFstrbuf secondPretty; //37
} FFDateTimeResult;
const FFDateTimeResult* ffDetectDateTime();
#endif
+8 -2
View File
@@ -7,7 +7,7 @@ static int compareDisks(const void* disk1, const void* disk2)
return ffStrbufCompAlphabetically(&((const FFDisk*) disk1)->mountpoint, &((const FFDisk*) disk2)->mountpoint);
}
const char* ffDetectDisks(FFlist* disks)
const char* ffDetectDisks(FFDiskOptions* options, FFlist* disks)
{
const char* error = ffDetectDisksImpl(disks);
@@ -22,7 +22,13 @@ const char* ffDetectDisks(FFlist* disks)
FF_LIST_FOR_EACH(FFDisk, disk, *disks)
{
if(disk->bytesTotal == 0)
disk->type |= FF_DISK_TYPE_UNKNOWN_BIT;
disk->type |= FF_DISK_VOLUME_TYPE_UNKNOWN_BIT;
else
{
disk->bytesUsed = disk->bytesTotal - (
options->calcType == FF_DISK_CALC_TYPE_FREE ? disk->bytesFree : disk->bytesAvailable
);
}
}
return NULL;
+5 -2
View File
@@ -7,12 +7,15 @@
typedef struct FFDisk
{
FFstrbuf mountFrom;
FFstrbuf mountpoint;
FFstrbuf filesystem;
FFstrbuf name;
FFDiskType type;
FFDiskVolumeType type;
uint64_t bytesUsed;
uint64_t bytesFree;
uint64_t bytesAvailable;
uint64_t bytesTotal;
uint32_t filesUsed;
@@ -23,6 +26,6 @@ typedef struct FFDisk
* Returns a List of FFDisk, sorted alphabetically by mountpoint.
* If error is not set, disks contains at least one disk.
*/
const char* ffDetectDisks(FFlist* result /* list of FFDisk */);
const char* ffDetectDisks(FFDiskOptions* options, FFlist* result /* list of FFDisk */);
#endif
-17
View File
@@ -1,17 +0,0 @@
#include "disk.h"
#include <sys/mount.h>
#import <Foundation/Foundation.h>
void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
// FreeBSD doesn't support these flags
if(fs->f_flags & MNT_DONTBROWSE)
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
else if(fs->f_flags & MNT_REMOVABLE)
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
else
disk->type = FF_DISK_TYPE_REGULAR_BIT;
ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String);
}
+56 -18
View File
@@ -1,42 +1,70 @@
#include "disk.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include <sys/mount.h>
#ifdef __FreeBSD__
#include "util/stringUtils.h"
static void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
if(ffStrbufEqualS(&disk->filesystem, "zfs"))
{
disk->type = !ffStrStartsWith(fs->f_mntfromname, "zroot/") || ffStrStartsWith(fs->f_mntfromname, "zroot/ROOT/")
? FF_DISK_TYPE_REGULAR_BIT
: FF_DISK_TYPE_SUBVOLUME_BIT;
disk->type = !ffStrbufStartsWithS(&disk->mountFrom, "zroot/") || ffStrbufStartsWithS(&disk->mountFrom, "zroot/ROOT/")
? FF_DISK_VOLUME_TYPE_REGULAR_BIT
: FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
}
else if(!ffStrStartsWith(fs->f_mntfromname, "/dev/"))
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi"))
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
else if(!(fs->f_flags & MNT_LOCAL))
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else
disk->type = FF_DISK_TYPE_REGULAR_BIT;
ffStrbufInit(&disk->name);
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
}
#elif __APPLE__
#include "util/apple/cf_helpers.h"
#include <sys/attr.h>
#include <unistd.h>
struct VolAttrBuf {
uint32_t length;
attrreference_t volNameRef;
char volNameSpace[MAXPATHLEN];
} __attribute__((aligned(4), packed));
void detectFsInfo(struct statfs* fs, FFDisk* disk)
{
if(fs->f_flags & MNT_DONTBROWSE)
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
else if(fs->f_flags & MNT_REMOVABLE || !(fs->f_flags & MNT_LOCAL))
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
struct VolAttrBuf attrBuf;
if (getattrlist(disk->mountpoint.chars, &(struct attrlist) {
.bitmapcount = ATTR_BIT_MAP_COUNT,
.volattr = ATTR_VOL_INFO | ATTR_VOL_NAME,
}, &attrBuf, sizeof(attrBuf), 0) == 0)
ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace);
}
#else
void detectFsInfo(struct statfs* fs, FFDisk* disk);
#endif
const char* ffDetectDisksImpl(FFlist* disks)
{
struct statfs* buf;
int size = getfsstat(NULL, 0, MNT_WAIT);
int size = getmntinfo(&buf, MNT_WAIT);
if(size <= 0)
return "getmntinfo(&buf, MNT_WAIT) failed";
return "getfsstat(NULL, 0, MNT_WAIT) failed";
FF_AUTO_FREE struct statfs* buf = malloc(sizeof(*buf) * (unsigned) size);
if(getfsstat(buf, (int) (sizeof(*buf) * (unsigned) size), MNT_NOWAIT) <= 0)
return "getfsstat(buf, size, MNT_NOWAIT) failed";
for(struct statfs* fs = buf; fs < buf + size; ++fs)
{
FFDisk* disk = ffListAdd(disks);
if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
continue;
#ifdef __FreeBSD__
// f_bavail and f_ffree are signed on FreeBSD...
@@ -44,15 +72,25 @@ const char* ffDetectDisksImpl(FFlist* disks)
if(fs->f_ffree < 0) fs->f_ffree = 0;
#endif
FFDisk* disk = ffListAdd(disks);
disk->bytesTotal = fs->f_blocks * fs->f_bsize;
disk->bytesUsed = disk->bytesTotal - ((uint64_t)fs->f_bfree * fs->f_bsize);
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->filesTotal = (uint32_t) fs->f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree);
ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname);
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
ffStrbufInitS(&disk->filesystem, fs->f_fstypename);
ffStrbufInit(&disk->name);
disk->type = 0;
detectFsInfo(fs, disk);
if(fs->f_flags & MNT_RDONLY)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
return NULL;
+132 -104
View File
@@ -1,5 +1,6 @@
#include "disk.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <limits.h>
@@ -7,6 +8,8 @@
#include <dirent.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <mntent.h>
#include <sys/mount.h>
#ifdef __USE_LARGEFILE64
#define stat stat64
@@ -15,77 +18,60 @@
#define readdir readdir64
#endif
static bool isPhysicalDevice(FFstrbuf* device)
static bool isPhysicalDevice(const struct mntent* device)
{
#ifndef __ANDROID__ //On Android, `/dev` is not accessable, so that the following checks always fail
//https://askubuntu.com/a/1289123
if(ffStrbufEqualS(device, "/cow"))
//Always show the root path
if(ffStrEquals(device->mnt_dir, "/"))
return true;
//DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem.
if(ffStrbufEqualS(device, "drvfs"))
if(ffStrEquals(device->mnt_fsname, "drvfs"))
return true;
//ZFS root pool. The format is rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>
if(ffStrbufStartsWithS(device, "rpool/"))
//ZFS pool
if(ffStrEquals(device->mnt_type, "zfs"))
return true;
//Pseudo filesystems don't have a device in /dev
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
return false;
if(
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices
) return false;
struct stat deviceStat;
if(stat(device->chars, &deviceStat) != 0)
if(stat(device->mnt_fsname, &deviceStat) != 0)
return false;
//Ignore all devices that are not block devices
if(!S_ISBLK(deviceStat.st_mode))
return false;
#else
//Pseudo filesystems don't have a device in /dev
if(!ffStrbufStartsWithS(device, "/dev/"))
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
return false;
#endif // __ANDROID__
if(
ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices
ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices
ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices
ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices
ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices
ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices
) return false;
#endif // __ANDROID__
return true;
}
static void appendNextEntry(FFstrbuf* buffer, char** source)
{
//Read the current entry into the buffer
while(**source != '\0' && !isspace(**source))
{
//After a backslash the next 3 characters are octal ascii codes
if(**source == '\\' && strnlen(*source, 4) == 4)
{
char octal[4] = {0};
strncpy(octal, *source + 1, 3);
long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr
if(value > 0 && value < CHAR_MAX)
{
ffStrbufAppendC(buffer, (char) value);
*source += 4;
continue;
}
}
ffStrbufAppendC(buffer, **source);
++*source;
}
//Skip whitespace
while(isspace(**source))
++*source;
}
static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath)
{
DIR* dir = opendir(basePath->chars);
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath->chars);
if(dir == NULL)
return;
@@ -110,18 +96,24 @@ static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFst
ffStrbufAppendS(&disk->name, entry->d_name);
break;
}
closedir(dir);
}
static void detectName(FFDisk* disk, const FFstrbuf* device)
static void detectName(FFDisk* disk)
{
struct stat deviceStat;
if(stat(device->chars, &deviceStat) != 0)
if(stat(disk->mountFrom.chars, &deviceStat) != 0)
return;
FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate();
//Detect USB devices. Code is put here to reuse deviceStat
//https://stackoverflow.com/a/73302717
ffStrbufAppendS(&basePath, "/dev/disk/by-id/");
detectNameFromPath(disk, &deviceStat, &basePath);
if (ffStrbufStartsWithS(&disk->name, "usb-"))
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
ffStrbufClear(&disk->name);
//Try label first
ffStrbufSetS(&basePath, "/dev/disk/by-label/");
detectNameFromPath(disk, &deviceStat, &basePath);
@@ -133,6 +125,8 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
detectNameFromPath(disk, &deviceStat, &basePath);
}
if (disk->name.length == 0) return;
// Basic\x20data\x20partition
for (uint32_t i = ffStrbufFirstIndexS(&disk->name, "\\x");
i != disk->name.length;
@@ -152,52 +146,100 @@ static void detectName(FFDisk* disk, const FFstrbuf* device)
#ifdef __ANDROID__
static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options)
static void detectType(FF_MAYBE_UNUSED const FFlist* disks, FFDisk* currentDisk)
{
if(ffStrbufEqualS(&currentDisk->mountpoint, "/") || ffStrbufEqualS(&currentDisk->mountpoint, "/storage/emulated"))
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/mnt/media_rw/"))
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
}
#else
static bool isSubvolume(const FFlist* devices)
static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk)
{
const FFstrbuf* current = ffListGet(devices, devices->length - 1);
if(ffStrbufEqualS(current, "drvfs")) // WSL Windows drives
if(ffStrbufEqualS(&currentDisk->mountFrom, "drvfs")) // WSL Windows drives
return false;
//Filter all disks which device was already found. This catches BTRFS subvolumes.
for(uint32_t i = 0; i < devices->length - 1; i++)
if(ffStrbufEqualS(&currentDisk->filesystem, "zfs"))
{
const FFstrbuf* otherDevice = ffListGet(devices, i);
//ZFS subvolumes
uint32_t index = ffStrbufFirstIndexC(&currentDisk->mountFrom, '/');
if (index == currentDisk->mountFrom.length)
return false;
if(ffStrbufEqual(current, otherDevice))
return true;
FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->mountFrom.chars);
for(uint32_t i = 0; i < disks->length - 1; i++)
{
const FFDisk* otherDevice = ffListGet(disks, i);
if(ffStrbufEqualS(&otherDevice->filesystem, "zfs") && ffStrbufStartsWith(&otherDevice->mountFrom, &zpoolName))
return true;
}
return false;
}
else
{
//Filter all disks which device was already found. This catches BTRFS subvolumes.
for(uint32_t i = 0; i < disks->length - 1; i++)
{
const FFDisk* otherDevice = ffListGet(disks, i);
//ZFS subvolumes: rpool/<POOL_NAME>/<VOLUME_NAME>/<SUBVOLUME_NAME>.
//Test if the third slash is present.
if(ffStrbufStartsWithS(current, "rpool/") && ffStrHasNChars(current->chars, '/', 3))
return true;
if(ffStrbufEqual(&currentDisk->mountFrom, &otherDevice->mountFrom))
return true;
}
}
return false;
}
static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options)
static bool isRemovable(FFDisk* currentDisk)
{
if(isSubvolume(devices))
currentDisk->type = FF_DISK_TYPE_SUBVOLUME_BIT;
else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL)
currentDisk->type = FF_DISK_TYPE_EXTERNAL_BIT;
// https://stackoverflow.com/a/73302025
// Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does.
// USB devices should be handled in detectName
FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/sys/block/");
FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath.chars);
if(dir == NULL)
return false;
uint32_t index = ffStrbufLastIndexC(&currentDisk->mountFrom, '/');
const char* partitionName = index == currentDisk->mountFrom.length ? NULL : currentDisk->mountFrom.chars + index + 1;
if (!partitionName || !*partitionName) return false;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_name[0] == '.')
continue;
if (!ffStrStartsWith(partitionName, entry->d_name)) continue;
// /sys/block/sdx/removable
ffStrbufAppendS(&basePath, entry->d_name);
ffStrbufAppendS(&basePath, "/removable");
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1");
}
return false;
}
static void detectType(const FFlist* disks, FFDisk* currentDisk)
{
if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return;
if(isRemovable(currentDisk))
currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else if(isSubvolume(disks, currentDisk))
currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT;
else if(ffStrbufStartsWithS(&currentDisk->mountpoint, "/boot") || ffStrbufStartsWithS(&currentDisk->mountpoint, "/efi"))
currentDisk->type = FF_DISK_TYPE_HIDDEN_BIT;
currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
else
currentDisk->type = FF_DISK_TYPE_REGULAR_BIT;
currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
}
#endif
@@ -209,69 +251,55 @@ static void detectStats(FFDisk* disk)
memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
disk->bytesUsed = disk->bytesTotal - (fs.f_bfree * fs.f_frsize);
disk->bytesFree = fs.f_bfree * fs.f_frsize;
disk->bytesAvailable = fs.f_bavail * fs.f_frsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
if(fs.f_flag & ST_RDONLY)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
const char* ffDetectDisksImpl(FFlist* disks)
{
FILE* mountsFile = fopen("/proc/mounts", "r");
FILE* mountsFile = setmntent("/proc/mounts", "r");
if(mountsFile == NULL)
return "fopen(\"/proc/mounts\", \"r\") == NULL";
return "setmntent(\"/proc/mounts\", \"r\") == NULL";
FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof(FFstrbuf));
struct mntent* device;
char* line = NULL;
size_t len = 0;
while(getline(&line, &len, mountsFile) != EOF)
while((device = getmntent(mountsFile)))
{
//Format of the file: "<device> <mountpoint> <filesystem> <options> ..." (Same as fstab)
char* currentPos = line;
//detect device
FFstrbuf* device = ffListAdd(&devices);
ffStrbufInit(device);
appendNextEntry(device, &currentPos);
if(!isPhysicalDevice(device))
{
ffStrbufDestroy(device);
devices.length--;
continue;
}
//We have a valid device, add it to the list
FFDisk* disk = ffListAdd(disks);
disk->type = FF_DISK_VOLUME_TYPE_NONE;
//detect mountFrom
ffStrbufInitS(&disk->mountFrom, device->mnt_fsname);
//detect mountpoint
ffStrbufInit(&disk->mountpoint);
appendNextEntry(&disk->mountpoint, &currentPos);
ffStrbufInitS(&disk->mountpoint, device->mnt_dir);
//detect filesystem
ffStrbufInit(&disk->filesystem);
appendNextEntry(&disk->filesystem, &currentPos);
ffStrbufInitS(&disk->filesystem, device->mnt_type);
//detect name
ffStrbufInit(&disk->name);
detectName(disk, device);
detectName(disk); // Also detects external devices
//detect type
detectType(&devices, disk, currentPos);
detectType(disks, disk);
//Detects stats
detectStats(disk);
}
if(line != NULL)
free(line);
FF_LIST_FOR_EACH(FFstrbuf, device, devices)
ffStrbufDestroy(device);
fclose(mountsFile);
endmntent(mountsFile);
return NULL;
}
+24 -8
View File
@@ -1,7 +1,9 @@
#include "disk.h"
#include "common/io/io.h"
#include "util/windows/unicode.h"
#include <windows.h>
#include <winioctl.h>
#include <assert.h>
const char* ffDetectDisksImpl(FFlist* disks)
@@ -25,20 +27,31 @@ const char* ffDetectDisksImpl(FFlist* disks)
FFDisk* disk = ffListAdd(disks);
ffStrbufInitWS(&disk->mountpoint, mountpoint);
uint64_t bytesFree;
if(!GetDiskFreeSpaceExW(mountpoint, NULL, (PULARGE_INTEGER)&disk->bytesTotal, (PULARGE_INTEGER)&bytesFree))
wchar_t volumeName[64];
if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName)))
ffStrbufInitWS(&disk->mountFrom, volumeName);
else
ffStrbufInit(&disk->mountFrom);
if(!GetDiskFreeSpaceExW(
mountpoint,
(PULARGE_INTEGER)&disk->bytesAvailable,
(PULARGE_INTEGER)&disk->bytesTotal,
(PULARGE_INTEGER)&disk->bytesFree
))
{
disk->bytesTotal = 0;
bytesFree = 0;
disk->bytesFree = 0;
disk->bytesAvailable = 0;
}
disk->bytesUsed = disk->bytesTotal - bytesFree;
disk->bytesUsed = 0; // To be filled in ./disk.c
if(driveType == DRIVE_REMOVABLE || driveType == DRIVE_REMOTE || driveType == DRIVE_CDROM)
disk->type = FF_DISK_TYPE_EXTERNAL_BIT;
disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT;
else if(driveType == DRIVE_FIXED)
disk->type = FF_DISK_TYPE_REGULAR_BIT;
disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT;
else
disk->type = FF_DISK_TYPE_HIDDEN_BIT;
disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT;
ffStrbufInit(&disk->filesystem);
ffStrbufInit(&disk->name);
@@ -47,11 +60,12 @@ const char* ffDetectDisksImpl(FFlist* disks)
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
DWORD diskFlags;
BOOL result = GetVolumeInformationW(mountpoint,
diskName, sizeof(diskName) / sizeof(*diskName), //Volume name
NULL, //Serial number
NULL, //Max component length
NULL, //File system flags
&diskFlags, //File system flags
diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem)
);
SetErrorMode(errorMode);
@@ -60,6 +74,8 @@ const char* ffDetectDisksImpl(FFlist* disks)
{
ffStrbufSetWS(&disk->filesystem, diskFileSystem);
ffStrbufSetWS(&disk->name, diskName);
if(diskFlags & FILE_READ_ONLY_VOLUME)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
}
//Unsupported
+67
View File
@@ -0,0 +1,67 @@
#include "diskio.h"
#include "common/time.h"
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options);
static FFlist ioCounters1;
static uint64_t time1;
void ffPrepareDiskIO(FFDiskIOOptions* options)
{
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
ffDiskIOGetIoCounters(&ioCounters1, options);
time1 = ffTimeGetNow();
}
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options)
{
const char* error = NULL;
if (time1 == 0)
{
ffListInit(&ioCounters1, sizeof(FFDiskIOResult));
error = ffDiskIOGetIoCounters(&ioCounters1, options);
if (error)
return error;
time1 = ffTimeGetNow();
}
if (ioCounters1.length == 0)
return "No physical disk found";
uint64_t time2 = ffTimeGetNow();
while (time2 - time1 < 1000)
{
ffTimeSleep((uint32_t) (1000 - (time2 - time1)));
time2 = ffTimeGetNow();
}
error = ffDiskIOGetIoCounters(result, options);
if (error)
return error;
if (result->length != ioCounters1.length)
return "Different number of physical disks. Hardware change?";
for (uint32_t i = 0; i < result->length; ++i)
{
FFDiskIOResult* icPrev = (FFDiskIOResult*)ffListGet(&ioCounters1, i);
FFDiskIOResult* icCurr = (FFDiskIOResult*)ffListGet(result, i);
if (!ffStrbufEqual(&icPrev->name, &icCurr->name))
return "Network interface name changed";
static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout");
for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t))
{
uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
uint64_t temp = *currValue;
*currValue -= *prevValue;
*currValue /= (time2 - time1) / 1000 /* seconds */;
*prevValue = temp;
}
}
time1 = time2;
return NULL;
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "fastfetch.h"
typedef enum FFDiskIOPhysicalType
{
FF_DISKIO_PHYSICAL_TYPE_UNKNOWN,
FF_DISKIO_PHYSICAL_TYPE_HDD,
FF_DISKIO_PHYSICAL_TYPE_SSD,
} FFDiskIOPhysicalType;
typedef struct FFDiskIOResult
{
FFstrbuf name;
FFstrbuf interconnect;
FFDiskIOPhysicalType type;
FFstrbuf devPath;
uint64_t bytesRead;
uint64_t readCount;
uint64_t bytesWritten;
uint64_t writeCount;
} FFDiskIOResult;
const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options);
+89
View File
@@ -0,0 +1,89 @@
#include "diskio.h"
#include "util/apple/cf_helpers.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOBlockStorageDriver.h>
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
static inline void wrapIoObjectRelease(io_service_t* service)
{
assert(service);
if (*service)
IOObjectRelease(*service);
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry;
io_name_t deviceName;
if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS)
continue;
if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0;
if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS)
continue;
if (!IOObjectConformsTo(entryDriver, kIOBlockStorageDriverClass)) // physical disk only
continue;
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef statistics = IORegistryEntryCreateCFProperty(entryDriver, CFSTR(kIOBlockStorageDriverStatisticsKey), kCFAllocatorDefault, kNilOptions);
if (!statistics)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInitS(&device->name, deviceName);
ffStrbufInit(&device->devPath);
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), (int64_t*) &device->bytesRead);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), (int64_t*) &device->bytesWritten);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsReadsKey), (int64_t*) &device->readCount);
ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsWritesKey), (int64_t*) &device->writeCount);
FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions);
if (bsdName)
{
ffCfStrGetString(bsdName, &device->devPath);
ffStrbufPrependS(&device->devPath, "/dev/");
}
ffStrbufInit(&device->interconnect);
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0;
if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS)
{
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
if (protocolCharacteristics)
ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->interconnect);
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions);
if (deviceCharacteristics)
{
CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey));
if (mediumType)
{
if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0)
device->type = FF_DISKIO_PHYSICAL_TYPE_SSD;
else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0)
device->type = FF_DISKIO_PHYSICAL_TYPE_HDD;
}
}
}
}
return NULL;
}
+51
View File
@@ -0,0 +1,51 @@
#include "diskio.h"
#include <devstat.h>
#include <memory.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
if (devstat_checkversion(NULL) < 0)
return "devstat_checkversion() failed";
struct statinfo stats = {
.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)),
};
if (devstat_getdevs(NULL, &stats) < 0)
return "devstat_getdevs() failed";
for (int i = 0; i < stats.dinfo->numdevs; i++)
{
struct devstat* current = &stats.dinfo->devices[i];
if (current->device_type & DEVSTAT_TYPE_PASS)
continue;
char deviceName[128];
snprintf(deviceName, sizeof(deviceName), "%s%d", current->device_name, current->unit_number);
if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInitS(&device->name, deviceName);
ffStrbufInitF(&device->devPath, "/dev/%s", deviceName);
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
ffStrbufInit(&device->interconnect);
switch (current->device_type & DEVSTAT_TYPE_IF_MASK)
{
case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break;
case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break;
case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break;
}
device->bytesRead = current->bytes[DEVSTAT_READ];
device->readCount = current->operations[DEVSTAT_READ];
device->bytesWritten = current->bytes[DEVSTAT_WRITE];
device->writeCount = current->operations[DEVSTAT_WRITE];
}
if (stats.dinfo->mem_ptr)
free(stats.dinfo->mem_ptr);
free(stats.dinfo);
return NULL;
}
+108
View File
@@ -0,0 +1,108 @@
#include "diskio.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <ctype.h>
#include <limits.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS("/dev/disk/by-id/");
uint32_t baseDirLength = baseDir.length;
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
if(dirp == NULL)
return "opendir(batteryDir) == NULL";
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.')
continue;
char* part = strstr(entry->d_name, "-part");
if (part && isdigit(part[strlen("-part")]))
continue;
if (ffStrStartsWith(entry->d_name, "nvme-eui.")) // NVMe drive indentifier
continue;
// Other exceptions?
ffStrbufAppendS(&baseDir, entry->d_name);
char pathDev[PATH_MAX];
ssize_t pathLen = readlink(baseDir.chars, pathDev, PATH_MAX);
ffStrbufSubstrBefore(&baseDir, baseDirLength);
if (pathLen < 0) continue;
pathDev[pathLen] = '\0'; // ../../nvme0n1
char pathDev1[PATH_MAX];
const char* devName = basename(pathDev);
snprintf(pathDev1, PATH_MAX, "/dev/%s", devName);
// Avoid duplicated disks
bool flag = false;
FF_LIST_FOR_EACH(FFDiskIOResult, disk, *result)
{
if (ffStrbufEqualS(&disk->devPath, pathDev1))
{
flag = true;
break;
}
}
if (flag) continue;
char pathSysBlock[PATH_MAX];
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName);
FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlock, "r");
if (!sysBlockStat) continue;
// I/Os merges sectors ticks ...
uint64_t nRead, sectorRead, nWritten, sectorWritten;
if (fscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, &sectorRead, &nWritten, &sectorWritten) == 0)
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
char* slash = strchr(entry->d_name, '-');
if (slash)
{
char* slash2 = strchr(slash + 1, '-');
if (slash2)
ffStrbufInitNS(&device->name, (uint32_t) (slash2 - slash - 1), slash + 1);
else
ffStrbufInitS(&device->name, slash + 1);
ffStrbufInitNS(&device->interconnect, (uint32_t) (slash - entry->d_name), entry->d_name);
}
else
{
ffStrbufInitS(&device->name, entry->d_name);
ffStrbufInit(&device->interconnect);
}
ffStrbufReplaceAllC(&device->name, '_', ' ');
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->interconnect);
result->length--;
continue;
}
ffStrbufInitS(&device->devPath, pathDev1);
device->bytesRead = sectorRead * 512;
device->bytesWritten = sectorWritten * 512;
device->readCount = nRead;
device->writeCount = nWritten;
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffReadFileBuffer(pathSysBlock, &buffer))
device->type = ffStrbufEqualS(&buffer, "1") ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD;
else
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
}
return NULL;
}
+89
View File
@@ -0,0 +1,89 @@
#include "diskio.h"
#include "common/io/io.h"
#include "util/windows/registry.h"
#include "util/windows/unicode.h"
#include <winioctl.h>
const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
{
FF_HKEY_AUTO_DESTROY hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", &hKey, NULL))
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum\") failed";
uint32_t nDevices;
if (!ffRegReadUint(hKey, L"Count", &nDevices, NULL))
return "ffRegReadUint(hKey, L\"Count\", &nDevices) failed";
wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive";
wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive");
for (uint32_t idev = 0; idev <= nDevices; ++idev) {
_ultow(idev, pNum, 10);
FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
continue;
DISK_PERFORMANCE diskPerformance;
DWORD ioctrlSize = sizeof(diskPerformance);
DWORD dwSize;
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, ioctrlSize, &dwSize, NULL))
{
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInit(&device->name);
ffStrbufInit(&device->interconnect);
if (ffRegReadStrbuf(hKey, pNum, &device->name, NULL))
{
// SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000
uint32_t index = ffStrbufFirstIndexC(&device->name, '\\');
if (index != device->name.length)
{
ffStrbufAppendNS(&device->interconnect, index, device->name.chars); // SCSI
ffStrbufSubstrAfter(&device->name, index);
}
ffStrbufSubstrBeforeLastC(&device->name, '\\');
ffStrbufSubstrAfterFirstS(&device->name, "&Ven_");
ffStrbufRemoveS(&device->name, "&Prod");
ffStrbufReplaceAllC(&device->name, '_', ' ');
ffStrbufTrim(&device->name, ' ');
}
else
ffStrbufSetWS(&device->name, szDevice);
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
{
ffStrbufDestroy(&device->name);
ffStrbufDestroy(&device->interconnect);
result->length--;
continue;
}
ffStrbufInitWS(&device->devPath, szDevice);
device->bytesRead = (uint64_t) diskPerformance.BytesRead.QuadPart;
device->readCount = (uint64_t) diskPerformance.ReadCount;
device->bytesWritten = (uint64_t) diskPerformance.BytesWritten.QuadPart;
device->writeCount = (uint64_t) diskPerformance.WriteCount;
DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {};
DWORD retSize = 0;
if(DeviceIoControl(
hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&(STORAGE_PROPERTY_QUERY) {
.PropertyId = StorageDeviceSeekPenaltyProperty,
.QueryType = PropertyStandardQuery,
},
sizeof(STORAGE_PROPERTY_QUERY),
&dspd,
sizeof(dspd),
&retSize,
NULL
) && retSize == sizeof(dspd))
device->type = dspd.IncursSeekPenalty ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD;
else
device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN;
}
}
return NULL;
}
@@ -80,9 +80,9 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
ffStrbufContainC(&buffer, ','))
{
// 1440,3200,560 => width,height,ppi
uint32_t width = ffStrbufToUInt16(&buffer, 0);
uint32_t width = (uint32_t) ffStrbufToUInt(&buffer, 0);
ffStrbufSubstrAfterFirstC(&buffer, ',');
uint32_t height = ffStrbufToUInt16(&buffer, 0);
uint32_t height = (uint32_t) ffStrbufToUInt(&buffer, 0);
return ffdsAppendDisplay(ds,
width,
height,
+17
View File
@@ -233,6 +233,23 @@ static void getXFCE4(FFDisplayServerResult* result)
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
#ifdef __FreeBSD__
if(result->deVersion.length == 0)
{
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/");
if (dirp)
{
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5]))
continue;
ffStrbufAppendS(&result->deVersion, &entry->d_name[5]);
}
}
}
#endif
if(result->deVersion.length == 0 && instance.config.allowSlowOperations)
{
//This is somewhat slow
+11 -4
View File
@@ -116,6 +116,7 @@ typedef struct XrandrData
{
FF_LIBRARY_SYMBOL(XInternAtom)
FF_LIBRARY_SYMBOL(XGetAtomName);
FF_LIBRARY_SYMBOL(XFree);
FF_LIBRARY_SYMBOL(XRRGetScreenInfo)
FF_LIBRARY_SYMBOL(XRRConfigCurrentConfiguration)
FF_LIBRARY_SYMBOL(XRRConfigCurrentRate)
@@ -207,9 +208,11 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true);
if (atomEdid != None)
{
unsigned long nitems = 0;
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
Atom actual_type = None;
uint8_t* edidData = NULL;
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, 0, 0, AnyPropertyType, NULL, NULL, &nitems, NULL, &edidData) == Success)
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success)
{
if (nitems >= 128)
{
@@ -217,6 +220,8 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
ffEdidGetName(edidData, name);
}
}
if (edidData)
data->ffXFree(edidData);
}
bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary);
@@ -228,8 +233,9 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
{
bool foundOutput = false;
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(data->ffXGetAtomName(data->display, monitorInfo->name));
char* xname = data->ffXGetAtomName(data->display, monitorInfo->name);
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(xname);
data->ffXFree(xname);
for(int i = 0; i < monitorInfo->noutput; i++)
{
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary))
@@ -341,6 +347,7 @@ void ffdsConnectXrandr(FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XInternAtom,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XGetAtomName,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XFree,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRGetScreenInfo,)
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentRate,);
FF_LIBRARY_LOAD_SYMBOL_VAR(xrandr, data, XRRConfigCurrentConfiguration,);
+1 -1
View File
@@ -130,7 +130,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126))
ffStrbufSetWS(&device->name, displayName);
else
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId);
ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId);
}
}
+1 -2
View File
@@ -30,9 +30,8 @@ static double detectGpuTemp(const FFstrbuf* gpuName)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
CFMutableDictionaryRef matchDict = IOServiceMatching(kIOAcceleratorClassName);
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
io_registry_entry_t registryEntry;
+6
View File
@@ -311,6 +311,12 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
{
#ifdef FF_HAVE_DIRECTX_HEADERS
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
if (!ffGPUDetectByDirectX(options, gpus))
return NULL;
#endif
#ifdef FF_HAVE_LIBPCI
return pciDetectGPUs(options, gpus);
#else
+102
View File
@@ -0,0 +1,102 @@
#ifdef FF_HAVE_DIRECTX_HEADERS
#define INITGUID
extern "C" {
#include "common/library.h"
#include "detection/gpu/gpu.h"
}
#include <wsl/winadapter.h>
#include <directx/dxcore.h>
#include <directx/d3d12.h>
#include <dxguids/dxguids.h>
#include <utility>
#include <cinttypes>
template <typename Fn>
struct on_scope_exit {
on_scope_exit(Fn &&fn): _fn(std::move(fn)) {}
~on_scope_exit() { this->_fn(); }
private:
Fn _fn;
};
extern "C"
const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
{
FF_LIBRARY_LOAD(libdxcore, nullptr, "dlopen libdxcore.so failed. Make sure WSLg is enabled", "/usr/lib/wsl/lib/libdxcore" FF_LIBRARY_EXTENSION, 4)
// DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here
typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory);
auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(libdxcore, "DXCoreCreateAdapterFactory");
if(ffDXCoreCreateAdapterFactory == nullptr) return "dlsym DXCoreCreateAdapterFactory failed";
IDXCoreAdapterFactory *factory = nullptr;
if (FAILED(ffDXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory))))
return "DXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory)) failed";
on_scope_exit destroyFactory([&] { factory->Release(); });
IDXCoreAdapterList *list = NULL;
if (FAILED(factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list)))
return "factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list) failed";
on_scope_exit destroyList([&] { list->Release(); });
for (uint32_t i = 0, count = list->GetAdapterCount(); i < count; i++)
{
IDXCoreAdapter *adapter = nullptr;
if (FAILED(list->GetAdapter(i, &adapter)))
continue;
on_scope_exit destroyAdapter([&] { adapter->Release(); });
// https://learn.microsoft.com/en-us/windows/win32/api/dxcore_interface/ne-dxcore_interface-dxcoreadapterproperty
{
bool value = 0;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsHardware, sizeof(value), &value)) && !value)
continue;
}
char desc[256];
if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, sizeof(desc), desc)))
continue;
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
ffStrbufInitS(&gpu->name, desc);
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
ffStrbufInit(&gpu->driver);
uint64_t value = 0;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverVersion, sizeof(value), &value)))
{
ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64 ".%" PRIu64 ".%" PRIu64,
(value >> 48) & 0xFFFF,
(value >> 32) & 0xFFFF,
(value >> 16) & 0xFFFF,
(value >> 0) & 0xFFFF);
}
gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DedicatedAdapterMemory, sizeof(value), &value)))
gpu->dedicated.total = value;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::SharedSystemMemory, sizeof(value), &value)))
gpu->shared.total = value;
gpu->type = FF_GPU_TYPE_UNKNOWN;
bool integrated;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, sizeof(integrated), &integrated)))
gpu->type = integrated ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
ffStrbufInit(&gpu->vendor);
DXCoreHardwareID hardwareId;
if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId)))
{
const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID);
ffStrbufAppendS(&gpu->vendor, vendorStr);
}
}
return NULL;
}
#endif
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#ifndef FF_INCLUDED_detection_libc_libc
#define FF_INCLUDED_detection_libc_libc
#include "fastfetch.h"
typedef struct FFLibcResult
{
const char* name;
const char* version;
} FFLibcResult;
const char* ffDetectLibc(FFLibcResult* result);
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "libc.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#include <features.h>
const char* ffDetectLibc(FFLibcResult* result)
{
#if __ANDROID_NDK__
result->name = "ndk-bionic";
result->version = FF_STR(__NDK_MAJOR__) "." FF_STR(__NDK_MINOR__) "." FF_STR(__NDK_BUILD__)
#if __NDK_BETA__
"-beta" FF_STR(__NDK_BETA__)
#elif __NDK_CANARY__
"-canary"
#endif
;
return NULL;
#else
return "Unknown Android libc";
#endif
}
+13
View File
@@ -0,0 +1,13 @@
#include "libc.h"
const char* ffDetectLibc(FFLibcResult* result)
{
result->name = "libSystem";
#ifdef FF_LIBSYSTEM_VERSION
result->version = FF_LIBSYSTEM_VERSION;
#else
result->version = NULL;
#endif
return NULL;
}
+13
View File
@@ -0,0 +1,13 @@
#include "libc.h"
const char* ffDetectLibc(FFLibcResult* result)
{
result->name = "FBSD";
#ifdef FF_FBSD_VERSION
result->version = FF_FBSD_VERSION;
#else
result->version = NULL;
#endif
return NULL;
}
+26
View File
@@ -0,0 +1,26 @@
#include "libc.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#include <features.h>
const char* ffDetectLibc(FFLibcResult* result)
{
#ifdef __UCLIBC__
result->name = "uClibc";
result->version = FF_STR(__UCLIBC_MAJOR__) "." FF_STR(__UCLIBC_MINOR__) "." FF_STR(__UCLIBC_SUBLEVEL__);
#elif defined(__GNU_LIBRARY__)
result->name = "glibc";
result->version = FF_STR(__GLIBC__) "." FF_STR(__GLIBC_MINOR__);
#else
result->name = "musl";
#ifdef FF_MUSL_VERSION
result->version = FF_MUSL_VERSION;
#else
result->version = NULL;
#endif
#endif
return NULL;
}
+65
View File
@@ -0,0 +1,65 @@
extern "C"
{
#include "libc.h"
}
#ifdef __MINGW32__
#include <_mingw.h>
#endif
template<uint32_t Major, uint32_t Minor>
class version_t {
constexpr static auto buflen() noexcept {
unsigned int len = 2; // "."
if (Major == 0)
len++;
else
for (auto n = Major; n; len++, n /= 10);
if (Minor == 0)
len++;
else
for (auto n = Minor; n; len++, n /= 10);
return len;
}
char buf[buflen()] = {};
public:
constexpr version_t() noexcept {
auto ptr = buf + buflen();
*--ptr = '\0';
if (Minor == 0) {
*--ptr = '0';
} else {
for (auto n = Minor; n; n /= 10)
*--ptr = "0123456789"[n % 10];
}
*--ptr = '.';
if (Major == 0) {
*--ptr = '0';
} else {
for (auto n = Major; n; n /= 10)
*--ptr = "0123456789"[n % 10];
}
}
constexpr operator const char *() const { return buf; }
};
template<uint32_t Major, uint32_t Minor>
constexpr version_t<Major, Minor> version;
extern "C"
const char* ffDetectLibc(FFLibcResult* result)
{
#ifdef _UCRT
result->name = "ucrt";
#else
result->name = "msvcrt";
#endif
result->version = version<(__MSVCRT_VERSION__ >> 8), (__MSVCRT_VERSION__ & 8)>;
return NULL;
}
-4
View File
@@ -12,10 +12,6 @@ typedef struct FFLocalIpResult
FFstrbuf ipv6;
FFstrbuf mac;
bool defaultRoute;
#ifdef _WIN32
uint32_t ifIndex;
#endif
} FFLocalIpResult;
const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results);
+14 -125
View File
@@ -1,5 +1,7 @@
#include "localip.h"
#include "common/io/io.h"
#include "common/netif/netif.h"
#include "util/stringUtils.h"
#include <string.h>
#include <ctype.h>
@@ -11,124 +13,11 @@
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <net/if_dl.h>
#include <net/route.h>
#include <sys/socket.h>
#else
#include <netpacket/packet.h>
#endif
#if defined(__linux__)
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
{
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
if (!netRoute) return false;
// skip first line
flockfile(netRoute);
while (getc_unlocked(netRoute) != '\n');
funlockfile(netRoute);
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small");
while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2)
{
if (destination == 0)
return true;
}
return false;
}
#elif defined(__FreeBSD__) || defined(__APPLE__)
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
#if defined(__APPLE__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__NetBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
#elif defined(__FreeBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#elif defined(__OpenBSD__)
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
#else
# error unknown platform
#endif
static struct sockaddr *
get_rt_address(struct rt_msghdr *rtm, int desired)
{
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
for (int i = 0; i < RTAX_MAX; i++)
{
if (rtm->rtm_addrs & (1 << i))
{
if ((1 <<i ) == desired)
return sa;
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
}
}
return NULL;
}
static bool getDefaultRoute(char iface[IF_NAMESIZE + 1])
{
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
if (pfRoute < 0)
return false;
{
struct timeval timeout = {1, 0};
setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));
}
int pid = getpid();
struct {
struct rt_msghdr hdr;
struct sockaddr_in dst;
uint8_t data[512];
} rtmsg = {
.hdr = {
.rtm_type = RTM_GET,
.rtm_flags = RTF_UP | RTF_GATEWAY,
.rtm_version = RTM_VERSION,
.rtm_addrs = RTA_DST | RTA_IFP,
.rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst),
.rtm_pid = pid,
.rtm_seq = 1,
},
.dst = {
.sin_family = AF_INET,
.sin_len = sizeof(rtmsg.dst),
},
};
if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen)
return false;
while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0)
{
if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid)
{
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP);
if (sdl)
{
assert(sdl->sdl_nlen <= IF_NAMESIZE);
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
iface[sdl->sdl_nlen] = 0;
return true;
}
return false;
}
}
return false;
}
#endif
static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute)
{
FFLocalIpResult* ip = NULL;
@@ -145,7 +34,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type)
ffStrbufInit(&ip->ipv4);
ffStrbufInit(&ip->ipv6);
ffStrbufInit(&ip->mac);
ip->defaultRoute = false;
ip->defaultRoute = defaultRoute;
}
switch (type)
@@ -168,11 +57,17 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
if(getifaddrs(&ifAddrStruct) < 0)
return "getifaddrs(&ifAddrStruct) failed";
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
continue;
bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name);
if (options->defaultRouteOnly && !isDefaultRoute)
continue;
if ((ifa->ifa_flags & IFF_LOOPBACK) && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT))
continue;
@@ -187,7 +82,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET);
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute);
}
else if (ifa->ifa_addr->sa_family == AF_INET6)
{
@@ -197,7 +92,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6);
addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute);
}
#if defined(__FreeBSD__) || defined(__APPLE__)
else if (ifa->ifa_addr->sa_family == AF_LINK)
@@ -209,7 +104,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr);
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute);
}
#else
else if (ifa->ifa_addr->sa_family == AF_PACKET)
@@ -221,18 +116,12 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr;
snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x",
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
addNewIp(results, ifa->ifa_name, addressBuffer, -1);
addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute);
}
#endif
}
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
char iface[16 /*IF_NAMESIZE*/ + 1];
if (getDefaultRoute(iface))
{
FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results)
ip->defaultRoute = ffStrbufEqualS(&ip->name, iface);
}
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More