mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
664 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 865929b173 | |||
| 9324136f52 | |||
| f601d2d9f5 | |||
| 54de7c8c96 | |||
| 3bb3bd542e | |||
| e6e7572bc2 | |||
| 884d256a34 | |||
| ed8430fb2f | |||
| 7fc1f0098e | |||
| 3839ee60d6 | |||
| 6f266a1609 | |||
| 026489c934 | |||
| 1d03747ec3 | |||
| a2919f5b2e | |||
| 680978b0d3 | |||
| af813dee00 | |||
| c281c46fff | |||
| 1f5e56c69e | |||
| 35d431dd3f | |||
| 6a2e8de563 | |||
| 9528cf96f0 | |||
| 66deb4316b | |||
| 61e9db97b9 | |||
| 66fbda9542 | |||
| 5137a9e7a4 | |||
| f76981c241 | |||
| 85050f7ff1 | |||
| 0b39d6fc59 | |||
| b7dd7fea0a | |||
| cc51596e5c | |||
| b566ffe81b | |||
| 60c06a888c | |||
| 8ceda02bbb | |||
| c005bc50c2 | |||
| 52411f6e37 | |||
| 31f620c041 | |||
| fdbd8d9ad5 | |||
| 1cad1dfdb0 | |||
| 4a1037d2b6 | |||
| dbcd5b922a | |||
| 8982b860f9 | |||
| 373b4353bb | |||
| ace336dfa9 | |||
| 4060626382 | |||
| 9f9e3dd931 | |||
| 3ed5a250a4 | |||
| fc969b01c7 | |||
| 41e22ea866 | |||
| 0b4a6055c6 | |||
| b340d4e149 | |||
| 878e516880 | |||
| 4e3673a2bb | |||
| 10c8c1b4bf | |||
| 17e3853f38 | |||
| 1bc41dfa54 | |||
| 8c227ae4b8 | |||
| c5c2589f4d | |||
| b273693842 | |||
| 52de8df1f9 | |||
| be99c4ca6e | |||
| 8133c3365f | |||
| 6226ccc70e | |||
| 88917cb14f | |||
| a93e2aafdb | |||
| 5848b5fc24 | |||
| 934b6291e3 | |||
| 90068ab474 | |||
| 5567e6cc5e | |||
| 8b3017c0d9 | |||
| f9f15ba844 | |||
| b282ac5d47 | |||
| 6577884417 | |||
| c4ee606955 | |||
| 59c80820f2 | |||
| c11e14f7e1 | |||
| ab6a770155 | |||
| 0e99486efe | |||
| f82f3002e4 | |||
| 0bed182784 | |||
| d39be955b1 | |||
| 3b2790cccc | |||
| 3ea0406b69 | |||
| 6429c20466 | |||
| 88ebeb21e2 | |||
| f28f5e2874 | |||
| 637c37e81c | |||
| b2c779dea9 | |||
| 89d636447b | |||
| 3dc51d5f88 | |||
| 60ff89c794 | |||
| f973572c5a | |||
| ea78665971 | |||
| 80b48dd2d1 | |||
| df6eed7a02 | |||
| c9ac09f9eb | |||
| 67597e4566 | |||
| 611de77980 | |||
| 0fde835629 | |||
| f373e07847 | |||
| 89e4403cc8 | |||
| c68d21e215 | |||
| f14cd2c6e8 | |||
| d58d786c83 | |||
| 9f37557177 | |||
| aa63c4f5f2 | |||
| a378d2ad62 | |||
| 2ab2dd4d48 | |||
| 2a83b86ba4 | |||
| d967d05019 | |||
| 9ef8580d93 | |||
| 813b80c5a8 | |||
| ddce9b2357 | |||
| 9342d74c93 | |||
| d6028370e7 | |||
| e425d7df63 | |||
| a4a2ae7d67 | |||
| 99aa0638cc | |||
| 1a9e637134 | |||
| f322405c04 | |||
| e4202635af | |||
| 2f13ee3814 | |||
| 2bfde87f84 | |||
| f38a51c9bc | |||
| 28ec935c42 | |||
| d939f95c69 | |||
| e0fd5111fe | |||
| 4736031538 | |||
| 66085c087e | |||
| e0253d71c0 | |||
| dadd4bfab6 | |||
| 2f3861e732 | |||
| 851f271ed5 | |||
| d3e40f625b | |||
| 7c1991c2e3 | |||
| b8048ee488 | |||
| b99f54b9f4 | |||
| b38d7a4919 | |||
| 45f7e2c0b2 | |||
| 5a8dda27ff | |||
| 1ea3264b13 | |||
| 852a729581 | |||
| 0f454b7140 | |||
| 9c47a3a9e7 | |||
| 4adf7fda28 | |||
| e2fc83fd48 | |||
| dd41dfa000 | |||
| 14d6157901 | |||
| 74586a9df1 | |||
| c5d4b20729 | |||
| b152b383a2 | |||
| ae26692ef6 | |||
| 4f807f26a9 | |||
| 4bef801337 | |||
| 41240e9460 | |||
| 3bb82423b3 | |||
| b87df82d58 | |||
| c145ce49a5 | |||
| 8c4fb5d6d4 | |||
| eae0fee032 | |||
| 4472a13f41 | |||
| 5b001d6bd6 | |||
| 1b52029fce | |||
| 2176ea2937 | |||
| ac2266c72f | |||
| 0dc40a2632 | |||
| ca975f8e81 | |||
| c4c6fe6668 | |||
| 0a00f5721e | |||
| 69f180beea | |||
| 0e9cdf75b5 | |||
| 7d7e219c0a | |||
| 4937ccfa81 | |||
| d0d29c163b | |||
| 901e0eb177 | |||
| 87446e6eef | |||
| bfaa73a2c7 | |||
| 373e288d03 | |||
| 82170ceab0 | |||
| 009a7888b5 | |||
| ab1a11c9fa | |||
| 68746275f8 | |||
| 491cfb94b6 | |||
| 79c8919431 | |||
| e98afa8315 | |||
| 86783c033b | |||
| f01944de41 | |||
| ebfdeef25c | |||
| 9a36d63d18 | |||
| e45ff546ed | |||
| 2700390371 | |||
| 5c01685d69 | |||
| d897472572 | |||
| 8410a66277 | |||
| 856d229b36 | |||
| b33692aa7d | |||
| e90c5cb241 | |||
| 03cd283755 | |||
| 58a1d965cb | |||
| 6edf763f2b | |||
| ab200d7e4a | |||
| dfe36daf79 | |||
| e9ab67b380 | |||
| f073f4882c | |||
| 692ad502df | |||
| 3004ce8565 | |||
| ee8801b54d | |||
| bbe239647b | |||
| 77c06193d6 | |||
| 90bbefe11a | |||
| 69a7e64e48 | |||
| ee564de461 | |||
| 9955e9da02 | |||
| 8b41cbd508 | |||
| 7535ce8a18 | |||
| b76eb87510 | |||
| 0cd7aeac19 | |||
| 04088b5b2c | |||
| e77c3119ca | |||
| 3463fc331f | |||
| 64287eed21 | |||
| 1b835544b6 | |||
| 55352be0cc | |||
| c0be2637a8 | |||
| 864fb918bc | |||
| 2197cfb06d | |||
| 94f8ff938b | |||
| 7000317841 | |||
| 06055cc6c3 | |||
| 601b9706b5 | |||
| d48c76b597 | |||
| 9a1d18556d | |||
| 71b073e1bf | |||
| a567268ca1 | |||
| 8b62ad72f7 | |||
| cee880cb83 | |||
| 925c3471c2 | |||
| 7948e627b0 | |||
| 4cca63a299 | |||
| 21a35769a7 | |||
| fa9290088d | |||
| 3d5133eaba | |||
| 4cbcd0f107 | |||
| fdc9bee4b3 | |||
| 16b7a4a1be | |||
| 465170428f | |||
| e953ed9d88 | |||
| 6d45fe61b5 | |||
| efc8504607 | |||
| a9a08d8a80 | |||
| 7f63ec1315 | |||
| 6cbbe334b5 | |||
| 4bde8d3fb3 | |||
| 62dcd1257e | |||
| dbb6a4b265 | |||
| a73a3089af | |||
| dcdf2b570e | |||
| ba7d3ed27b | |||
| b7a9fe58b4 | |||
| e5451b6826 | |||
| 9f314a208b | |||
| 56eb8b80c6 | |||
| 563ed58b4f | |||
| b8ec07092a | |||
| e77a4e8262 | |||
| 782af250ff | |||
| 6801fe3d9c | |||
| 1c41c6ccb1 | |||
| c9e3f8d95c | |||
| 97e1b987dd | |||
| e821a99873 | |||
| bad85a557a | |||
| 1d92bf864a | |||
| 2cfc8ec0db | |||
| 5efb87997b | |||
| d7fa0417ed | |||
| fe57b28581 | |||
| 5a1be2535b | |||
| bccf241816 | |||
| c70c37c50c | |||
| 644458bc74 | |||
| e618303343 | |||
| 748b7df0d7 | |||
| 7c8250c68c | |||
| c368908b7d | |||
| 830c71ddc4 | |||
| 5e7d9ed45e | |||
| 4799f9277e | |||
| 0a61031463 | |||
| 07d0743a18 | |||
| f989a1a982 | |||
| f9713d5ee2 | |||
| 4f9645e7ff | |||
| 08a92a4324 | |||
| d10c14721a | |||
| 4534f18525 | |||
| f98e6c9d4e | |||
| 59c666515a | |||
| 7fab6f27ee | |||
| 7d406bbae1 | |||
| 7b81ffc8e4 | |||
| 0284e4ccc4 | |||
| 837903e845 | |||
| 3fa0d1ab19 | |||
| 07f2a71b3c | |||
| acb38fa3ee | |||
| 7396208809 | |||
| 2389d7b580 | |||
| 8f750da559 | |||
| f69a9dab33 | |||
| 9a34cb98dc | |||
| ef974ef8c0 | |||
| 40671c78f1 | |||
| 211fd4b197 | |||
| 722063401c | |||
| 9be70a73d3 | |||
| 55909c480e | |||
| 7ceabcc03e | |||
| e4b98b3494 | |||
| 991ebfbc4a | |||
| 02e133bf35 | |||
| 3c6214d90f | |||
| 7f56928cf0 | |||
| 1487c91f3f | |||
| 47b9d0a3a4 | |||
| 17d6153353 | |||
| b5545c926f | |||
| a7f881522b | |||
| 91fdc8114f | |||
| 8f2d51c698 | |||
| 534aa09d86 | |||
| d216391278 | |||
| 743babda10 | |||
| 9610912c1f | |||
| 282ed9b40b | |||
| d1ef454ae8 | |||
| 5c21931a09 | |||
| 3c04b0ae65 | |||
| dab02f176f | |||
| f7288fec01 | |||
| 540239fe03 | |||
| fe8595a054 | |||
| efe0676831 | |||
| 565afa1e51 | |||
| 7ffffda504 | |||
| 0110584e39 | |||
| 254f1216ec | |||
| 090b6d741c | |||
| b05023fb8b | |||
| 0f3ce426e9 | |||
| 7d46b2ada5 | |||
| e0acce9646 | |||
| b410710903 | |||
| cb403be8e5 | |||
| 2bc66d7f27 | |||
| d4c7b53ded | |||
| c693e5ab5f | |||
| cae8286621 | |||
| c3d04d067d | |||
| 49902d8c2f | |||
| 229d5f899c | |||
| 3f41306c91 | |||
| 6ccc6124d0 | |||
| c6c6803403 | |||
| e22b58b26e | |||
| 0406f5c2b2 | |||
| 5443334156 | |||
| a3a042f02b | |||
| bc550a5ea7 | |||
| 82fc27f259 | |||
| 081e8ea39f | |||
| e7630aef34 | |||
| e19ed4c8f6 | |||
| 332ddfc6ed | |||
| 32939eabab | |||
| bdd87a6ce7 | |||
| 4665fdd145 | |||
| 2fe6e60d98 | |||
| 26920d49f5 | |||
| 2dc8ac6a51 | |||
| 20f9ff9bae | |||
| fd26373c8f | |||
| 6dc6fd8b24 | |||
| 53e0861b03 | |||
| 19902fa18c | |||
| f3f8601a60 | |||
| 0bdb097592 | |||
| b57766522d | |||
| 18d530103f | |||
| 4d235a9fe9 | |||
| 5c06d34b49 | |||
| 6cd7f6c2f6 | |||
| c8521b55b9 | |||
| 40b8023ff9 | |||
| 7a3afa4adf | |||
| b257134d74 | |||
| 5497cb64c2 | |||
| bd4bc87c38 | |||
| 188dbde595 | |||
| 48bb5b8746 | |||
| 9bd692dffb | |||
| dee5f1b339 | |||
| ecd73667df | |||
| 993902916d | |||
| 8f79d6ab1d | |||
| 6500cddc09 | |||
| 4146bb6731 | |||
| 9188715efd | |||
| bf1cd3388d | |||
| a0ad38d1d4 | |||
| cc86c2c428 | |||
| 67a35c92ff | |||
| ae76d2d032 | |||
| 2b2c223d22 | |||
| d6fa03d9e6 | |||
| 21ab56ad00 | |||
| b5a9d64e75 | |||
| e73d6db2e5 | |||
| 1c598add39 | |||
| f87f345918 | |||
| fba33df1d3 | |||
| a11b10fb37 | |||
| c73b5914ab | |||
| e70589483d | |||
| 71a8978f41 | |||
| 0f1ad5750d | |||
| bbc9cf4980 | |||
| fbed730dac | |||
| f847a23fb9 | |||
| c5527fa4e6 | |||
| c92d6f9eb6 | |||
| 3a914f2d27 | |||
| 986d36c028 | |||
| 746cff471f | |||
| 08cdeb3bcf | |||
| b5a8d6b86d | |||
| 29dd6d88c9 | |||
| 49076ec69d | |||
| 15fc3bcc92 | |||
| 1178f46aac | |||
| 68406cd044 | |||
| 782474b068 | |||
| cd9cfa5d99 | |||
| ded38efb1a | |||
| e2474d1238 | |||
| ec7c1855b3 | |||
| 99c0e9e719 | |||
| af09de319b | |||
| ff21dabfb7 | |||
| 27910cf6ec | |||
| daab70fafc | |||
| 4dccb92bb2 | |||
| 8c74745076 | |||
| 3eb081561d | |||
| 9dcfdcae83 | |||
| 4dbc9566da | |||
| 492010b325 | |||
| 6647d36f85 | |||
| ee29f767a0 | |||
| aece7cb550 | |||
| 6f0e6587ac | |||
| bf9963cf85 | |||
| a2b32ef564 | |||
| dbe7aaaa1b | |||
| d0f52162f3 | |||
| c624c36754 | |||
| 84cc9e3b15 | |||
| 8855c0b851 | |||
| 4059bca941 | |||
| bb94ac7832 | |||
| d5d935a658 | |||
| 44ccc69834 | |||
| 6bcfc3a61e | |||
| 2d356aa644 | |||
| 9ea887e841 | |||
| 5f3ce50022 | |||
| acfab74d4b | |||
| 24c3f0d6b9 | |||
| c2ec1e9606 | |||
| 951a15b61b | |||
| f30501f365 | |||
| bde6c3b829 | |||
| 7fac54e7b8 | |||
| d4c8a4c9fd | |||
| b34283eaf0 | |||
| 67964363e8 | |||
| 41a1b3a9d5 | |||
| 320283a538 | |||
| 40ab735e6b | |||
| 716bfe7cc1 | |||
| 84fc5b4503 | |||
| 729085e054 | |||
| a32d9d788c | |||
| d06f9a1509 | |||
| c2b60a2ebf | |||
| 937b2e41ed | |||
| aa734e2220 | |||
| a4fe933625 | |||
| 53a373c9cf | |||
| 46c8bc1f99 | |||
| 8a11aa0f8f | |||
| 89d3924659 | |||
| b49c509a6c | |||
| 99626149f6 | |||
| 3381262930 | |||
| 6dd6266a2a | |||
| 18be6c8fd1 | |||
| 5bdae7afc3 | |||
| 316849e5df | |||
| d5c395fb85 | |||
| 46eb0e4b1c | |||
| fb0a18dc82 | |||
| ca442b3da4 | |||
| a32361fdc5 | |||
| d77f0fe3d9 | |||
| 1df129083b | |||
| 2cd6cb3ca1 | |||
| eeb2d1c746 | |||
| d97999ddc9 | |||
| 70e8398f05 | |||
| 0b32abd5a7 | |||
| 73e61c2b89 | |||
| 1901b9308f | |||
| a7c7493733 | |||
| 73f98f9509 | |||
| 3d82d55e5d | |||
| 6485d34700 | |||
| 17c9179b7d | |||
| 88097463af | |||
| 5381395c54 | |||
| 51796de69a | |||
| 140b9834cc | |||
| a424839d2f | |||
| acd5d4a258 | |||
| f8fa3f8ea6 | |||
| 38f07ade44 | |||
| 7ae7ff8cef | |||
| 842ba9fd4e | |||
| 5058a93428 | |||
| d6eff93c12 | |||
| 03565384e6 | |||
| a3a4f0a64a | |||
| af067c7c3f | |||
| 8bbc985d98 | |||
| 254876b9e6 | |||
| 78fc5a2b5d | |||
| 745c041b44 | |||
| 4283d96c53 | |||
| e07fcc4d49 | |||
| d095f39418 | |||
| af63e6e98b | |||
| fc05d728f3 | |||
| e3cb52583d | |||
| 01735d6fde | |||
| b37b495aee | |||
| 28c9b67414 | |||
| 4d7d367e72 | |||
| 8295f66320 | |||
| 87f2e69162 | |||
| f496e6d965 | |||
| 96d885e93a | |||
| ae6817e106 | |||
| 582b0fa087 | |||
| 0414128a55 | |||
| 5dbd6b9ab8 | |||
| 0c90941a32 | |||
| 29ae56e76a | |||
| 81b0ddb2da | |||
| 4ea5d6f4fe | |||
| 9b4053e9dc | |||
| b4325ff205 | |||
| 87d32466f6 | |||
| 3b9d20ddf2 | |||
| 32b6af2686 | |||
| a3c0617f22 | |||
| 30ffa4bdd2 | |||
| 86a96da9ab | |||
| b3b6e5fec1 | |||
| e0296b75f6 | |||
| bd2b002d14 | |||
| c936d170b2 | |||
| a77d972834 | |||
| 10868ed951 | |||
| fc947468a9 | |||
| 005d660d77 | |||
| 866c7303e6 | |||
| 85a31c7c69 | |||
| 1dba6d155b | |||
| db669c00a1 | |||
| 006c00ab2c | |||
| 0bcbae90e9 | |||
| 503a8d51ab | |||
| 9332f42889 | |||
| 9d0797c308 | |||
| f80423607d | |||
| c49c857db2 | |||
| 174359dc3e | |||
| 43d6f81b01 | |||
| 0025c78cce | |||
| 5a9a2ca0fd | |||
| 6c8b4b25d2 | |||
| 6acc33cd16 | |||
| 756865855b | |||
| c64720c6da | |||
| 0eecdd16ea | |||
| acdd1fc69c | |||
| 1b9345267f | |||
| c24328e26e | |||
| c58f4c24c4 | |||
| 3381062ab9 | |||
| 553b0fe8cc | |||
| 74fcd8b1c3 | |||
| a1f0570a96 | |||
| cd11a9dff4 | |||
| ed2dd8f2ec | |||
| 9faa38296a | |||
| 3d1a6b67c5 | |||
| b1eceb6be2 | |||
| af450ae788 | |||
| 03c901b260 | |||
| 7bbaca2fab | |||
| ce90689ba3 | |||
| 0c4edf7d0e | |||
| 119de2e91a | |||
| e9bb761a2d | |||
| fd432e3635 | |||
| 174dde131c | |||
| 99668771c7 | |||
| dc541ac781 | |||
| 68ab41f748 | |||
| e8f711830e | |||
| a052033dc6 | |||
| fed2c87f67 | |||
| b7fcd7fc0c | |||
| b2810bc030 | |||
| 8f1f1607da | |||
| 611d5f949b | |||
| 536e2fb42d | |||
| 1e4601485a | |||
| f8c58a9178 | |||
| d8fb8d439e | |||
| de59ffb31f | |||
| c24d378cf1 | |||
| de8efb39c8 | |||
| 13452da076 | |||
| 7db8d7c3ce | |||
| f4424b4204 | |||
| 8371920c6b | |||
| c9d539090d | |||
| d43c6ffe27 | |||
| cf7c5d3cfa | |||
| 3f67fac4fa | |||
| 879d5594da | |||
| 32bf85742c | |||
| 37cc2c9c1b | |||
| c39df1ae7b | |||
| 4622604ee1 | |||
| 617661b546 | |||
| 9aae274cc7 | |||
| 90b2bf0ad6 | |||
| aec27c3e50 | |||
| d79bf0a460 | |||
| 352ed51504 | |||
| d824045973 | |||
| bbe4988054 |
+1
-1
@@ -2,4 +2,4 @@
|
||||
check-filenames =
|
||||
builtin = clear,rare,usage,informal
|
||||
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,conexant
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
github: [CarterLi, LinusDierheimer]
|
||||
@@ -1,80 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: '[BUG] '
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Be sure to read the [FAQ](https://github.com/fastfetch-cli/fastfetch?tab=readme-ov-file#faq) before submitting a new issue.
|
||||
|
||||
<!-- We will try hard to solve the issue. However since platforms and hardwares vary greatly, it can be hard to find the root cause of an issue. Providing the following information may help us greatly. Thanks in advance! -->
|
||||
|
||||
# General description of bug:
|
||||
|
||||
* What happened:
|
||||
* What should happen:
|
||||
* Fastfetch version used: <!-- please use the latest version, if possible -->
|
||||
* Did it work in an older version: <!-- if yes, which version -->
|
||||
* Where did you get the binary: <!-- GitHub release / GitHub Actions / installed with a package manager (please tell us which package manager you used!) / built from source yourself -->
|
||||
* Does this issue still occur in [the latest dev build](https://github.com/fastfetch-cli/fastfetch/actions/)?
|
||||
|
||||
# Often helpful information:
|
||||
|
||||
Screenshot:
|
||||
<!-- Paste the screenshot here -->
|
||||
|
||||
The content of the configuration file you use (if any):
|
||||
```
|
||||
// Paste here
|
||||
```
|
||||
|
||||
Output of `fastfetch -c ci.jsonc --format json`:
|
||||
<!--
|
||||
Note that this output will contain you public IP. If it is not relevant for the issue, feel free to remove it before uploading.
|
||||
-->
|
||||
|
||||
```
|
||||
// Paste here
|
||||
```
|
||||
|
||||
Output of `fastfetch --list-features`:
|
||||
```
|
||||
// Paste here
|
||||
```
|
||||
|
||||
## If fastfatch crashed or froze
|
||||
|
||||
Paste the stacktrace here. You may get it with:
|
||||
|
||||
```shell
|
||||
# You may need Ctrl+C to stop the process if it freezes
|
||||
gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
|
||||
```
|
||||
|
||||
If you are able to identify which module crashed, the strace can be helpful too
|
||||
|
||||
```shell
|
||||
strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
|
||||
```
|
||||
|
||||
If you cannot do the instructions above, please upload the core dump file:
|
||||
|
||||
## If fastfetch is slow
|
||||
|
||||
Use `time fastfetch --stat` to show time usage for each module.
|
||||
|
||||
## If an image or logo didn't show
|
||||
|
||||
<!-- Please make sure your terminal supports the image protocol you used. Note that GNOME Terminal doesn't support any image protocols. -->
|
||||
|
||||
* The image protocol you used:
|
||||
* The terminal you used:
|
||||
* Upload the image file here, or paste the image URL:
|
||||
* Does it work with `--logo-width {WIDTH} --logo-height {HEIGHT}`?
|
||||
|
||||
## If fastfetch behaves incorrectly on shell startup
|
||||
|
||||
* The bug is reproducible with a clean shell configuration (i.e. `fastfetch` is the only line in `.zshrc` or `~/.config/fish/config.fish`):
|
||||
* Does `sleep 1` before running `fastfetch` work?
|
||||
@@ -0,0 +1,113 @@
|
||||
name: Crash Bug Report
|
||||
description: If fastfetch crashes or freezes
|
||||
title: "[BUG] "
|
||||
labels: ["bug", "crash", "triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! We will try hard to solve the issue.
|
||||
However since platforms and hardwares vary greatly, it can be hard to find the root cause of an issue.
|
||||
Providing the following information may help us greatly. Thanks in advance!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Read the FAQ first
|
||||
description: Please check if the issue is already covered in the FAQ.
|
||||
options:
|
||||
- label: I have checked the FAQ but the issue is not covered
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### General description of the bug"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: I was trying to [...] but [...]
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version used
|
||||
description: Fastfetch version used. Please use the latest version (found in the [releases](https://github.com/fastfetch-cli/fastfetch/releases)) if possible.
|
||||
placeholder: Result of `fastfetch --version`
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Bug prevalence
|
||||
description: How often does the bug occur?
|
||||
options:
|
||||
-
|
||||
- Always
|
||||
- Sometimes
|
||||
- Rarely
|
||||
- Once
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Regression
|
||||
description: Did it work in an older version?
|
||||
options:
|
||||
-
|
||||
- Not sure
|
||||
- 'Yes'
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Installation
|
||||
description: Where did you install fastfetch from?
|
||||
options:
|
||||
-
|
||||
- GitHub Releases
|
||||
- GitHub Actions (nightly)
|
||||
- Built from source
|
||||
- Package manager
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Package manager
|
||||
description: Which package manager did you use if applicable?
|
||||
placeholder: e.g. `apt`, `pacman`, `brew`, `scoop`
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: '### Often helpful information'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: If applicable, paste your configuration file here.
|
||||
placeholder: cat ~/.config/fastfetch/config.jsonc
|
||||
render: jsonc
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Paste the stacktrace here. You may get it with:
|
||||
|
||||
```shell
|
||||
# You may need Ctrl+C to stop the process if it freezes
|
||||
gdb -q -ex 'set confirm off' -ex run -ex 'bt full' -ex quit --args /path/to/fastfetch
|
||||
```
|
||||
|
||||
If you are able to identify which module crashed, the strace can be helpful too
|
||||
|
||||
```shell
|
||||
strace /path/to/fastfetch --multithreading false -s {MODULE} --pipe
|
||||
```
|
||||
|
||||
If you cannot do the instructions above, please upload the core dump file if available.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Stacktrace
|
||||
description: Paste the stacktrace or core dump file here.
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,106 @@
|
||||
name: General Bug Report
|
||||
description: If something is not working as expected (wrong output, missing info, etc)
|
||||
title: "[BUG] "
|
||||
labels: ["bug", "triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! We will try hard to solve the issue.
|
||||
However since platforms and hardwares vary greatly, it can be hard to find the root cause of an issue.
|
||||
Providing the following information may help us greatly. Thanks in advance!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Read the FAQ first
|
||||
description: Please check if the issue is already covered in the FAQ.
|
||||
options:
|
||||
- label: I have checked the FAQ but the issue is not covered
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### General description of the bug"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: I was trying to [...] but [...]
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version used
|
||||
description: Fastfetch version used. Please use the latest version (found in the [releases](https://github.com/fastfetch-cli/fastfetch/releases)) if possible.
|
||||
placeholder: Result of `fastfetch --version`
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Bug prevalence
|
||||
description: How often does the bug occur?
|
||||
options:
|
||||
-
|
||||
- Always
|
||||
- Sometimes
|
||||
- Rarely
|
||||
- Once
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Regression
|
||||
description: Did it work in an older version?
|
||||
options:
|
||||
-
|
||||
- Not sure
|
||||
- 'Yes'
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Installation
|
||||
description: Where did you install fastfetch from?
|
||||
options:
|
||||
-
|
||||
- GitHub Releases
|
||||
- GitHub Actions (nightly)
|
||||
- Built from source
|
||||
- Package manager
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Package manager
|
||||
description: Which package manager did you use if applicable?
|
||||
placeholder: e.g. `apt`, `pacman`, `brew`, `scoop`
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: '### Often helpful information'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: If applicable, paste your configuration file here.
|
||||
placeholder: cat ~/.config/fastfetch/config.jsonc
|
||||
render: jsonc
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: System information
|
||||
description: Output of `fastfetch -c all.jsonc --stat --format json`
|
||||
placeholder: |
|
||||
Note that this output will contain you public IP.
|
||||
If it is not relevant for the issue, feel free to remove it before uploading.
|
||||
render: jsonc
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Features built-in
|
||||
description: Output of `fastfetch --list-features`
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,129 @@
|
||||
name: Logo Bug Report
|
||||
description: If my image logo is not displayed correctly
|
||||
title: "[BUG] "
|
||||
labels: ["bug", "logo", "triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! We will try hard to solve the issue.
|
||||
However since platforms and hardwares vary greatly, it can be hard to find the root cause of an issue.
|
||||
Providing the following information may help us greatly. Thanks in advance!
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Read the FAQ first
|
||||
description: Please check if the issue is already covered in the FAQ.
|
||||
options:
|
||||
- label: I have checked the FAQ but the issue is not covered
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "### General description of the bug"
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: I was trying to [...] but [...]
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version used
|
||||
description: Fastfetch version used. Please use the latest version (found in the [releases](https://github.com/fastfetch-cli/fastfetch/releases)) if possible.
|
||||
placeholder: Result of `fastfetch --version`
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Bug prevalence
|
||||
description: How often does the bug occur?
|
||||
options:
|
||||
-
|
||||
- Always
|
||||
- Sometimes
|
||||
- Rarely
|
||||
- Once
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Regression
|
||||
description: Did it work in an older version?
|
||||
options:
|
||||
-
|
||||
- Not sure
|
||||
- 'Yes'
|
||||
- 'No'
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Installation
|
||||
description: Where did you install fastfetch from?
|
||||
options:
|
||||
-
|
||||
- GitHub Releases
|
||||
- GitHub Actions (nightly)
|
||||
- Built from source
|
||||
- Package manager
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Package manager
|
||||
description: Which package manager did you use if applicable?
|
||||
placeholder: e.g. `apt`, `pacman`, `brew`, `scoop`
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: '### Often helpful information'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: If applicable, paste your configuration file here.
|
||||
placeholder: cat ~/.config/fastfetch/config.jsonc
|
||||
render: jsonc
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
#### If an image or logo didn't show
|
||||
|
||||
Please make sure your terminal supports the image protocol you used.
|
||||
Note that GNOME Terminal doesn't support any image protocols as of now
|
||||
|
||||
Some tips:
|
||||
1. Try `fastfetch --show-errors` to see if there are any errors.
|
||||
2. Try `fastfetch --logo-width {WIDTH} --logo-height {HEIGHT}`. Some protocols may require a image size being set.
|
||||
- type: input
|
||||
attributes:
|
||||
label: Image protocol
|
||||
description: The image protocol you used
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Terminal
|
||||
description: The terminal you used
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Image tried
|
||||
description: Upload the image file, or paste the image URL here
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Error message
|
||||
description: Error message printed by `fastfetch -s none --show-errors`, if any
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Features built-in
|
||||
description: Output of `fastfetch --list-features`
|
||||
render: text
|
||||
validations:
|
||||
required: true
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: '[FEAT] '
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Be sure to read [FAQ](https://github.com/fastfetch-cli/fastfetch?tab=readme-ov-file#faq) before submitting a new issue.
|
||||
|
||||
## Wanted features:
|
||||
|
||||
<!-- Your features here -->
|
||||
|
||||
## Motivation:
|
||||
|
||||
<!-- Your motivation here -->
|
||||
@@ -0,0 +1,40 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: "[FEAT] "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Fastfetch is a system information tool. We only accept hardware or system level software feature requests.
|
||||
For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script:
|
||||
|
||||
```jsonc
|
||||
// This module shows the git version
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"type": "command",
|
||||
"key": "Git",
|
||||
"text": "git version",
|
||||
"format": "{~12}" // cut the first 12 characters
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of what the feature is.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why do you want this feature? Why doesn't `Command` module suffice for you?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
name: Logo request
|
||||
about: Request a new logo
|
||||
title: '[LOGO] '
|
||||
labels: logo request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo. For highly customized logo for personal use, it's recommended to keep it locally. Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
|
||||
|
||||
# OS
|
||||
```
|
||||
Paste content of /etc/os-release and /etc/lsb-release here. If none of these files exist, describe a way to identify the distro
|
||||
```
|
||||
|
||||
# Ascii
|
||||
|
||||
An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
|
||||
|
||||
```
|
||||
Paste ascii art here.
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
name: Logo Request
|
||||
description: Request a new ASCII logo for your favorite distro
|
||||
title: "[LOGO] "
|
||||
labels: ["logo request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo.
|
||||
For highly customized logo for personal use, it's recommended to keep it locally.
|
||||
Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: OS
|
||||
description: Paste content of `/etc/os-release` and `/etc/lsb-release` here. If none of these files exist, describe a way to identify the distro
|
||||
placeholder: cat /etc/os-release
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: ASCII Art
|
||||
description: An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
|
||||
placeholder: Paste ASCII art here
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Original Image
|
||||
description: If the ASCII art is based on an image, please provide a link to the original image
|
||||
placeholder: Image URL or distro website URL
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: The ASCII art is smaller than 50x20 characters (width x height)
|
||||
required: true
|
||||
- label: The ASCII art contains color codes, or the color codes are available in `os-release`
|
||||
required: true
|
||||
+193
-123
@@ -35,7 +35,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev python3-requests
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -197,6 +197,42 @@ jobs:
|
||||
name: fastfetch-linux-armv7
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv6:
|
||||
name: Linux-armv6
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv6
|
||||
distro: bookworm
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y wget
|
||||
apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv6
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -232,6 +268,41 @@ jobs:
|
||||
name: fastfetch-linux-riscv64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-ppc64le:
|
||||
name: Linux-ppc64le
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: ppc64le
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-ppc64le
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
@@ -247,12 +318,12 @@ jobs:
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev py3-requests gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja .
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
@@ -272,50 +343,9 @@ jobs:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-aarch64:
|
||||
name: Musl-aarch64
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
with:
|
||||
branch: v3.19
|
||||
arch: aarch64
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: run
|
||||
run: |
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-musl-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-12
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -418,12 +448,12 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.1'
|
||||
version: '14.2'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py311-requests chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
@@ -438,6 +468,113 @@ jobs:
|
||||
name: fastfetch-freebsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
dragonfly-amd64:
|
||||
name: DragonFly-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
usesh: yes
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py39-requests chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
openbsd-amd64:
|
||||
name: OpenBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: openbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.6'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-openbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
netbsd-amd64:
|
||||
name: NetBSD-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: netbsd
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.0'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick pulseaudio opencl-headers ocl-icd py312-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
@@ -456,7 +593,7 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG64
|
||||
update: true
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt
|
||||
install: git mingw-w64-clang-x86_64-7zip mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-clang mingw-w64-clang-x86_64-vulkan-loader mingw-w64-clang-x86_64-vulkan-headers mingw-w64-clang-x86_64-opencl-icd mingw-w64-clang-x86_64-opencl-headers mingw-w64-clang-x86_64-cppwinrt mingw-w64-clang-x86_64-imagemagick
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
@@ -503,76 +640,6 @@ jobs:
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
|
||||
windows-i686:
|
||||
name: Windows-i686
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git p7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd mingw-w64-clang-i686-opencl-headers
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c, cpp
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang32/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: download amd_ags
|
||||
run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x86.dll
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-i686.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-i686.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-i686
|
||||
path: ./fastfetch-windows-i686.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
@@ -581,14 +648,17 @@ jobs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-armv7
|
||||
- linux-armv6
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- musl-amd64
|
||||
- musl-aarch64
|
||||
- macos-universal
|
||||
- freebsd-amd64
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- windows-amd64
|
||||
- windows-i686
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
@@ -9,3 +9,4 @@ tags
|
||||
fastfetch.kdev4
|
||||
*.user
|
||||
*.user.*
|
||||
*.swp
|
||||
|
||||
+423
@@ -1,3 +1,426 @@
|
||||
# 2.35.0
|
||||
|
||||
Bugfixes:
|
||||
* Suppress output of EGL again (#1513, GPU, Linux)
|
||||
* Regression of 2.34.0
|
||||
|
||||
Features:
|
||||
* Show SOC name reported in `cpuinfo` if available (#1510, CPU, Linux)
|
||||
* Change package manager name of NetBSD from `pkg` to `pkgsrc` (#1515, Packages, NetBSD)
|
||||
* Detect SOC name on RISCV (#1519, CPU, Linux)
|
||||
* Report marketing name of new QS8Es (CPU, Android)
|
||||
* Acquire acquire more os info from lsb-release if missing from os-release (#1521)
|
||||
* CMake: add option `-DCUSTOM_LSB_RELEASE_PATH` to specify the path of `lsb-release` file
|
||||
* `-DCUSTOM_OS_RELEASE_PATH` has been supported since `v2.11.4`
|
||||
* Report more SOC names on Android (CPU, Android)
|
||||
* Support duration printing in custom format (Disk / Users)
|
||||
* For example:
|
||||
```jsonc
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"key": "OS Installation Date", // No longer need to write bash scripts
|
||||
"type": "disk",
|
||||
"folders": "/", // Different OSes may need to specify different folders
|
||||
"format": "{create-time:10} [{days} days]" // Reports the creation date of the root folder
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Logo:
|
||||
* Add Arch_old
|
||||
* Update key color of NetBSD_small
|
||||
* Fix OpenBSD and many other ascii logos (#1522)
|
||||
|
||||
# 2.34.1
|
||||
|
||||
An early release to fix KDE Plasma 6.3 compatibility. Hopefully it can be accepted by package managers before KDE 6.3 is officially released.
|
||||
|
||||
To package managers: if you find fastfetch bugs, it's highly appreciated if you can report them to the upstream, so that all users can benefit from the fix, instead of maintaining out-of-tree patches. Thanks!
|
||||
|
||||
Features:
|
||||
* Report vendor name when detecting GPUs by OpenGL
|
||||
* Note: the vendor name is actually the creator of the OpenGL driver (such as `Mesa`) and may not be the same as the GPU vendor.
|
||||
|
||||
Bugfixes:
|
||||
* Fix Ghostty termfont detection (#1495, TerminalFont, macOS)
|
||||
* Fix compatibility with KDE Plasma 6.3 (#1504, Display, Linux)
|
||||
* Make memory usage detection logic consistent with other systems (Memory, OpenBSD / NetBSD)
|
||||
* Report media file name if media title is not available (Media)
|
||||
* Fix max frequency detection for CPUs with both performance and efficiency cores (CPU, FreeBSD)
|
||||
|
||||
Logo:
|
||||
* Add HeliumOS
|
||||
* Add Oreon
|
||||
* Update SnigdhaOS
|
||||
|
||||
# 2.34.0
|
||||
|
||||
Changes:
|
||||
* We now print distro pretty name if available (OS)
|
||||
* This is a long requested feature. However, it may break some distros. File a bug with the content of `/etc/os-release` if it breaks your distro.
|
||||
|
||||
Bugfixes:
|
||||
* Fix thunderbolt version of new MBPs (#1465, Host, macOS)
|
||||
* Fix backlight name detection on FreeBSD (Brightness, FreeBSD)
|
||||
* Fix Terminal detection when running fastfetch in `pk-command-not-found` (#1467, Terminal, Linux)
|
||||
* Relax detection of terminals in NixOS (#1479, Terminal, Linux)
|
||||
* Should fix konsole, ghostty and maybe others
|
||||
* Fix core count output in multi-package platforms (CPU)
|
||||
* Don't suppress the output of `preRun` (#1489)
|
||||
* Fix battery percentage detection (Battery, NetBSD)
|
||||
|
||||
Features:
|
||||
* Support ghostty terminal font detection (TerminalFont, Linux / macOS)
|
||||
* Support `kitty-icat` image protocol, which uses `kitten icat` to generate image data
|
||||
* Pros: support tmux; support gif animations; good performance
|
||||
* Cons: due to the limitation of `kitten icat`, we need to clear the screen before displaying the image logo
|
||||
* Support WM version detection (WM)
|
||||
* In Linux, Hyprland & sway are supported currently
|
||||
* Improve performance when stdout is redirected (TerminalSize)
|
||||
* Report thermal zone temp if CPU temp is not available (CPU, Linux)
|
||||
* Report sound server (Pipewire or PulseAudio) if available (#1454, Sound, Linux)
|
||||
* Enable OpenGL & OpenCL detection on Android (OpenGL / OpenCL, Android)
|
||||
* Detect & report MediaTek Dimensity 9000+ SOC name (CPU, Android)
|
||||
* Support appman (am-user) package manager detection (Packages, Linux)
|
||||
|
||||
Logo:
|
||||
* Add Lubuntu
|
||||
* Update Xray_os
|
||||
* Add SnigdhaOS
|
||||
* Add Rhino Linux
|
||||
|
||||
# 2.33.0
|
||||
|
||||
Changes:
|
||||
* Introduce a new CMake flag `-DBUILD_FLASHFETCH=OFF` to disable building flashfetch binaries
|
||||
* Package managers are encouraged to enable it. See <https://github.com/fastfetch-cli/fastfetch/discussions/627> for detail
|
||||
|
||||
Bugfixes:
|
||||
* Fix interconnect type detection (#1453, PhysicalDisk, Linux)
|
||||
* Regression of v2.28
|
||||
* Don't report `proot` as terminal (Terminal, Android)
|
||||
* Remove a debug output (DiskIO, OpenBSD)
|
||||
* Fix media detection for some players (#1461, Media, Linux)
|
||||
* Regression of v2.32
|
||||
|
||||
Features:
|
||||
* Use `$POWERSHELL_VERSION` as PowerShell version if available (Shell, Windows)
|
||||
* Fetching Windows PowerShell version can be very slow. Add `$env:POWERSHELL_VERSION = $PSVersionTable.PSVersion.ToString()` in `$PROFILE` before running `fastfetch` to improve the performance of `Shell` module
|
||||
* Add support for ubuntu-based armbian detection (#1447, OS, Linux)
|
||||
* Improve performance of Bluetooth detection (Bluetooth)
|
||||
* We no longer report disconnected bluetooth devices in `--format json` when `--bluetooth-show-disconnected` isn't specified
|
||||
* Support brightness level detection for builtin displays (Brightness, OpenBSD / NetBSD)
|
||||
* Requires root permission on OpenBSD
|
||||
* Support battery level detection (Battery, OpenBSD / NetBSD)
|
||||
* Support CPU temperature detection in NetBSD (CPU, NetBSD)
|
||||
* Hard code path of `libvulkan.so` for Android
|
||||
* So that users don't need to install the vulkan-loader wrapper of termux
|
||||
|
||||
Logo:
|
||||
* Add NurOS
|
||||
* Add GoralixOS
|
||||
|
||||
# 2.32.1
|
||||
|
||||
A hotfix for OpenBSD. No changes to other platforms.
|
||||
|
||||
Bugfixes:
|
||||
* Fix package count detection on OpenBSD (Packages, OpenBSD)
|
||||
|
||||
# 2.32.0
|
||||
|
||||
Bugfixes:
|
||||
* Fix `pci.ids` file location on OpenBSD (GPU, OpenBSD)
|
||||
* It's normally unused because enumerating PCI devices on OpenBSD requires root privileges
|
||||
* Fix bssid formatting (Wifi, Linux)
|
||||
* Fix Linux Lite distro detection (#1434, OS, Linux)
|
||||
* Suppress XE driver warnings from Mesa (#1435, OpenGL, Linux)
|
||||
* Fix format parameter name (#1443, Version)
|
||||
* Don't report useless information when Wifi is disabled (Wifi, FreeBSD)
|
||||
* Currently there are issues when the SSID contains whitespaces. More fixes are expected in the future.
|
||||
* Always use physical size reported by X11 server to avoid inconsistent results (#1444, Display, Linux)
|
||||
|
||||
Features:
|
||||
* Randomly select one if the logo source expands to multiple files (#1426, Logo)
|
||||
* Report mac product name when running Linux in MacBook (Host, Linux / FreeBSD)
|
||||
* Use screen size reported in DTD if make sense (Display)
|
||||
* Detect Virtualized Apple Silicon CPUs (CPU, Linux)
|
||||
* Add detection support for fvwm and ctwm (WM, OpenBSD / NetBSD)
|
||||
* Add Armbian-unofficial detection (OS, Linux)
|
||||
* Prefer surfaceless display when connect EGL (OpenGL)
|
||||
* Improve accuracy of WM detection on FreeBSD (WM, FreeBSD)
|
||||
* Add ratpoison window manager (WM, Linux)
|
||||
|
||||
Logo:
|
||||
* Update Linux Lite
|
||||
* Add Serpent OS
|
||||
* Add Ultramarine Small
|
||||
* Update Debian
|
||||
|
||||
# 2.31.0
|
||||
|
||||
Bugfixes:
|
||||
* Improve performance of media detection; fix musikcube detection (Media, Linux)
|
||||
* After the change, `general.processingTimeout` will also control the timeout of dbus remote calls
|
||||
* Fix invalid variable names (#1408, Users)
|
||||
* Change physical size detection to use basic display parameters (#1406)
|
||||
* Fix possible sigfaults when detecting displays (#1393)
|
||||
* Fix Nvidia card type detection
|
||||
* Fix wl-restart parsing (#1422, WM, Linux)
|
||||
* Fix syntax error in completion file (#1421)
|
||||
* Fix hunging when using `ssh-agent` as command text (#1418, Command, macOS)
|
||||
|
||||
Features:
|
||||
* Remove support of xcb & xlib and xrandr extension is always required (Display)
|
||||
* Support preferred resolution & refresh rate detection
|
||||
* On macOS there is no preferred resolution reported and maximum available resolution is reported instead.
|
||||
* `--display-format {preferred-width}x{preferred-height}@{preferred-refresh-rate}`
|
||||
* Report scale factor in custom format (Display)
|
||||
* `--display-format {scale-factor}`
|
||||
* Detect current Wi-Fi channel and maximum frequency (Wifi)
|
||||
* Report processor package count (#1413, CPU)
|
||||
* Remove duplicate whitespaces in CPU name
|
||||
* Support sakura terminal version & font detection (Terminal / TerminalFont, Linux)
|
||||
|
||||
Logo:
|
||||
* Fix LMDE
|
||||
* Update MidOS
|
||||
* Add Windows Server 2025
|
||||
|
||||
# 2.30.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix the destination where `fastfetch.1` is generated (#1403)
|
||||
|
||||
# 2.30.0
|
||||
|
||||
Changes:
|
||||
* Percent: bar type must be enabled in `percent.type` before using percent bar in custom format
|
||||
|
||||
Features:
|
||||
* Port to MidnightBSD; add mport package manager support
|
||||
* Support bluetooth battery detection for macOS and Windows (Bluetooth, macOS / Windows)
|
||||
* Support M4 model detection (Host, macOS)
|
||||
* Support CPU temperature detection on OpenBSD (CPU, OpenBSD)
|
||||
* Display Android icon in Android devices (OS, Android)
|
||||
* Support qi package manager detection (Packages, Linux)
|
||||
* Detect WM / DE by enumerating running processes (WM / DE, NetBSD)
|
||||
* Generate manual pages from `help.json` (Doc)
|
||||
* Detect marketing name of vivo smartphone (Host, Android)
|
||||
* Add txDrops detection if supported (NetIO, *BSD)
|
||||
* Support tilix version detection (Terminal, Linux)
|
||||
* Support percent type config in module level. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "memory",
|
||||
"percent": {
|
||||
"green": 20, // [0%, 20%) will be displayed in green
|
||||
"yellow": 40, // [20, 40) will be displayed in yellow and [40, 100] will be displayed in red
|
||||
"type": [ // Display percent value in monochrome bar, same as 10
|
||||
"bar",
|
||||
"bar-monochrome"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Don't display `()` in key if display name is not available (Display)
|
||||
* Fix & normalize bluetooth mac address detection (Bluetooth, macOS / Windows)
|
||||
* Don't print index in multi-battery devices (Battery)
|
||||
* Fix segfault in macOS (#1388, macOS)
|
||||
* Fix `CFStringGetCString() failed` errors (#1394, Media, macOS)
|
||||
* Fix CPU frequency detection on Apple M4 (#1394, CPU, macOS)
|
||||
* Fix exe path detection on macOS (Shell / Terminal, macOS)
|
||||
* Fix logo fails to load from symlinked files on macOS (#1395, Logo, macOS)
|
||||
* Fix 32-bit truncation (NetIO, macOS)
|
||||
|
||||
Logos:
|
||||
* Fix Lilidog
|
||||
* Add MidnightBSD
|
||||
* Add Unifi
|
||||
* Add Cosmic DE
|
||||
* Update openSUSE Tumbleweed
|
||||
|
||||
# 2.29.0
|
||||
|
||||
Changes:
|
||||
* Due to [the upstream removal of MSYS2 CLANG32 environment](https://www.msys2.org/news/#2024-09-23-starting-to-drop-the-clang32-environment), we dropped fastfetch-windows-i686 support. v2.27.1 was the last version supporting it.
|
||||
* Note: fastfetch built with MSVCRT has known bug that DateTime module doesn't work because of its bad support of [strftime](https://en.cppreference.com/w/c/chrono/strftime). Don't use it.
|
||||
|
||||
Features:
|
||||
* Port to NetBSD and DragonFly BSD
|
||||
* Fastfetch now supports all major BSD variants
|
||||
* Support DiskIO, NetIO, GPU and Users module on OpenBSD
|
||||
* Report SD8E SOC name (CPU, Android)
|
||||
* On Windows, try loading dlls from current exe path (Windows)
|
||||
* Fix Media module when installed with winget
|
||||
|
||||
Bugfixes:
|
||||
* Fix the VIM version detection on Ubuntu (Editor, Linux)
|
||||
* Improve performance of OS version detection on Proxmox (#1370, OS, Linux)
|
||||
|
||||
Logo:
|
||||
* Update OpenSuse Tumbleweed
|
||||
* Add XCP-ng
|
||||
* Add SummitOS
|
||||
* Add Lilidog
|
||||
* Update PikaOS
|
||||
* Update OpenSUSE Leap
|
||||
* Update aperture
|
||||
|
||||
# 2.28.0
|
||||
|
||||
Features:
|
||||
* Add new module `Mouse` and `Keyboard` which display connected mice and keyboards
|
||||
* Support remaining time detection (Battery)
|
||||
* Report if AC is connected (Battery, Linux)
|
||||
* Report platform API used for display detection for debugging (Display)
|
||||
* Report Wine version when running in Wine (Kernel, Windows)
|
||||
* Add option `waitTime` in modules `CPUUsage`, `DiskIO` and `NetIO`
|
||||
|
||||
Bugfixes:
|
||||
* Fix used memory size detection (Memory, OpenBSD)
|
||||
* Don't report invalid fragmentation percentage when fails to detect it (Zpool)
|
||||
* Fix unexpected errors when running fastfetch in parallel (#1346, Windows)
|
||||
* Don't report obviously invalid temperature values (PhysicalDisk, Linux)
|
||||
|
||||
Logos:
|
||||
* Add eweOS
|
||||
* Add MidOS
|
||||
* Update XeroArch
|
||||
|
||||
# 2.27.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix invalid display name detection on GNOME, wayland (Display, Linux)
|
||||
|
||||
# 2.27.0
|
||||
|
||||
Changes:
|
||||
* We now print `"` instead of `″` when displaying diagonal length in inches, so that the character can be correctly displayed in Linux console (Display)
|
||||
* All detection code of `monitor` module is merged into `display` module. Now `monitor` just prints the same information as `display` with different format. Notably:
|
||||
* The resolution reported by `monitor` module is now current resolution instead of native / maximum resolution. PPI is calculated based on current resolution too.
|
||||
* The refresh rate reported by `monitor` module is the current refresh rate.
|
||||
|
||||
Features:
|
||||
* Add basic, highly experimental support of OpenBSD (OpenBSD)
|
||||
* Improve support for Raspberry pi (CPU / GPU, Linux)
|
||||
* Detect SOC name, instead of displaying components used in the SOC, if available (CPU, Linux)
|
||||
* Add option `--brightness-compact` to display multiple brightness values in one line (Brightness)
|
||||
* Add `day-pretty` (#1305, DateTime)
|
||||
* Support network interface adapter flag detection (#1315, LocalIP)
|
||||
* Enable it with `--localip-show-flags`
|
||||
|
||||
Bugfixes:
|
||||
* Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux)
|
||||
* Fix a possible buffer overflow (GPU, Linux)
|
||||
* Fix CPU temp incorrectly reported as 0 celsius (#1308, CPU, Linux)
|
||||
* Correctly report `TPM device is not found` error (#1314, TPM, Windows)
|
||||
* Fix errors when triggering shell completion with python3 uninstalled (#1310)
|
||||
* To package managers: as shell completion scripts of fastfetch use python3, it should be added as an optional dependency of fastfetch
|
||||
* Fix possible crashes when detecting term font of kitty (#1321, TerminalFont, Linux)
|
||||
|
||||
Logos:
|
||||
* Add XeroArch
|
||||
* Add ValhallaOS
|
||||
|
||||
# 2.26.1
|
||||
|
||||
Features:
|
||||
* Allow to disable pacstall packager detection in CMake
|
||||
|
||||
Bugfixes:
|
||||
* Fix uninitialized variables (GPU, Windows)
|
||||
|
||||
# 2.26.0
|
||||
|
||||
Changes:
|
||||
* To be consistent to other platforms, CPU frequency detection on Linux no longer checks `bios_limit`
|
||||
|
||||
Features:
|
||||
* Detect GPU index (#1267, GPU)
|
||||
* Count Flatpak runtime packages (#1085, Packages, Linux)
|
||||
* Support pacstall package manager (Packages, Linux)
|
||||
* Support CU core count, max frequency, VMEM usage detection for AMD cards on Linux (GPU, Linux)
|
||||
* Requires `--gpu-driver-specific`
|
||||
* Support EU core count, VMEM size detection Intel cards on Linux (GPU, Linux)
|
||||
* Requires `--gpu-driver-specific`. VMEM usage detection requires root permissions.
|
||||
* Add new module `TPM` to print TPM (Trusted Platform Module) version if available (TPM)
|
||||
* Support GPU driver version detection (GPU, macOS)
|
||||
* Add new CMake option `-DENABLE_EMBEDDED_PCIIDS=ON`.
|
||||
* If enabled, fastfetch will download the newest [`pci.ids`](https://pci-ids.ucw.cz/) file, [transform it into C code](https://github.com/fastfetch-cli/fastfetch/blob/dev/scripts/gen-pciids.py) and compile it into fastfetch binaries.
|
||||
|
||||
Bugfixes:
|
||||
* Fix font size detecton of foot terminal (#1276, TerminalFont, Linux)
|
||||
* Ignore `su` and `sudo` when detecting terminal (#1283, Terminal, Linux)
|
||||
* Always print inches in integer (Display)
|
||||
* Fix Wifi connection protocol detection on macOS Sequoia (Wifi, macOS)
|
||||
* Fix hanging when font name is long when detecting kitty term font (#1289, TerminalFont)
|
||||
* Detect all enabled or connected connectors (#1301, Display, Linux)
|
||||
|
||||
Logos:
|
||||
* Add FoxOS
|
||||
* Add GXDE OS
|
||||
|
||||
# 2.25.0
|
||||
|
||||
Features:
|
||||
* Moore Threads GPU add support to query number of cores (#1259, GPU)
|
||||
* Cache detection result based on last modification time (Packages)
|
||||
* Add cmake options to disable certain package managers at compile time
|
||||
* Package managers are encouraged to disable some package managers by passing `-DPACKAGES_DISABLE_` when running `cmake`. For example, when building for Arch Linux, `-DPACKAGES_DISABLE_APK=ON -DPACKAGES_DISABLE_DPKG=ON -DPACKAGES_DISABLE_RPM=ON ...` should be specified.
|
||||
* See all available options by [running `cmake -L | grep PACKAGES_DISABLE_`](https://github.com/fastfetch-cli/fastfetch/blob/dev/CMakeLists.txt#L91)
|
||||
* This option does NOT remove the detection code. It just disables the detection at runtime. One can still use `--packages-disabled ""` to enable all package managers.
|
||||
* Add new option `--show-localip-{speed,mtu}` (LocalIP)
|
||||
* Add new module `Btrfs`, which prints all mounted Btrfs volumes, like `Zpool` module (#1262, Linux)
|
||||
* Improve Wifi module support for macOS Sequoia (Wifi, macOS)
|
||||
* Currently it uses `system_profiler` which costs about 2 seconds on my MBP. I suggest disabling it for now until a better solution is found.
|
||||
|
||||
Bugfixes:
|
||||
* Fix invalid CPU temperature detection on FreeBSD (#1260, CPU, FreeBSD)
|
||||
* Remove `showPeCoreCount` support on FreeBSD (#1260, CPU, FreeBSD)
|
||||
* Don't use Wifi speed as Ethernet speed (LocalIP, FreeBSD)
|
||||
* Fix compiling with old linux headers (Camera, Linux)
|
||||
* Fix detecting public ipv6 address (PublicIP, Windows)
|
||||
|
||||
Logo:
|
||||
* Fix parrot logo detection
|
||||
* Rename TorizonCore to Torizon OS
|
||||
|
||||
# 2.24.0
|
||||
|
||||
Changes:
|
||||
* Support of `--lib-XXX` is removed
|
||||
* If fastfetch fails to load some `.so` `.dylib` libraries, `LD_LIBRARY_PATH` should be used.
|
||||
|
||||
Features:
|
||||
* Support sixel image protocol on Windows (Logo, Windows)
|
||||
* Requires imagemagick7 to be installed. MSYS2 is recommended.
|
||||
* Improve terminal query on Windows (Windows)
|
||||
* TerminalSize, TerminalTheme
|
||||
* Detect more ARM microarchitectures and SOC names (CPU, Linux)
|
||||
* Detect the number of online cores (CPU, FreeBSD)
|
||||
* Support board name detection for Asahi Linux (Board, Linux)
|
||||
* Add new option `--command-param` to customize the parameters when running shell
|
||||
* Support syntax of sub string in `--<module>-format`: `{variable~startIndex,endIndex}`
|
||||
* See `fastfetch -h format` for detail
|
||||
|
||||
Bugfixes:
|
||||
* Fix tests building when system yyjson is used (#1244)
|
||||
* Fix dinit detection; support dinit version detection (#1245, InitSystem, Linux)
|
||||
* Fix signal quality, refresh rate and maybe others in custom format (#1241)
|
||||
* Fix boot time calculation (#1249, Uptime, Linux)
|
||||
* Fix custom format for boolean values
|
||||
* `{?false-value}This should not print{?}{?true-value}This should print{?}` will print `This should print`
|
||||
* Fix possible hanging when running fastfetch in screen 5.0 (TerminalTheme, macOS)
|
||||
|
||||
Logos:
|
||||
* Add Lliurex
|
||||
|
||||
# 2.23.0
|
||||
|
||||
Features:
|
||||
|
||||
+466
-99
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
|
||||
|
||||
### Linux
|
||||
|
||||
Some distros packaged an outdated fastfetch version. Older version receive no support, so please try always to use the latest version.
|
||||
Some distros package an outdated fastfetch version. Older versions receive no support, so please try always to use the latest version.
|
||||
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
@@ -40,7 +40,6 @@ Some distros packaged an outdated fastfetch version. Older version receive no su
|
||||
* openSUSE: `zypper install fastfetch`
|
||||
* ALT Linux: `apt-get install fastfetch`
|
||||
* Exherbo: `cave resolve --execute app-misc/fastfetch`
|
||||
* GNU Guix: `guix install fastfetch`
|
||||
* Solus: `eopkg install fastfetch`
|
||||
* Slackware: `sbopkg -i fastfetch`
|
||||
* Void Linux: `xbps-install fastfetch`
|
||||
@@ -81,7 +80,7 @@ See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
## Usage
|
||||
|
||||
* Run it with default configuration: `fastfetch`
|
||||
* Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what you interest: `fastfetch -c all.jsonc`
|
||||
* Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what interests you: `fastfetch -c all.jsonc`
|
||||
* Find all data that fastfetch detects: `fastfetch -s <module> --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --gen-config`
|
||||
@@ -90,7 +89,7 @@ See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
|
||||
Fastfetch uses the JSONC (or JSON with comments) for configuration. [See Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). There are some premade config files in [`presets`](presets), including the ones used for the screenshots above. You can load them using `-c <filename>`. Those files can serve as examples of the configuration syntax.
|
||||
|
||||
Logos can be heavily customized too; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
|
||||
## Packaging
|
||||
@@ -112,7 +111,7 @@ Logos can be heavily customized too; see the [logo documentation](https://github
|
||||
2. Fastfetch is faster. As the name suggests.
|
||||
3. Fastfetch has a greater number of features, though by default fastfetch only has a few modules enabled; use `fastfetch -c all` to find what you want.
|
||||
4. Fastfetch is more configurable. You can find more information in the Wiki: <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration>.
|
||||
5. Fastfetch is more polished. For example, neofetch prints `555MiB` in `Memory` module and `23G` in `Disk` module, whereas fastfetch prints `555.00 MiB` and `22.97 GiB` respectively.
|
||||
5. Fastfetch is more polished. For example, neofetch prints `555 MiB` in the Memory module and `23 G` in the Disk module, whereas fastfetch prints `555.00 MiB` and `22.97 GiB` respectively.
|
||||
6. Fastfetch is more accurate. For example, [neofetch never actually supports the Wayland protocol](https://github.com/dylanaraps/neofetch/pull/2395).
|
||||
|
||||
### Q: Fastfetch shows my local IP address. It leaks my privacy!
|
||||
@@ -152,13 +151,13 @@ Fastfetch uses `format` to generate output. For example, to make the `GPU` modul
|
||||
"modules": [
|
||||
{
|
||||
"type": "gpu",
|
||||
"format": "{2}" // See `fastfetch -h gpu-format` for detail
|
||||
"format": "{name}" // See `fastfetch -h gpu-format` for detail
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
. . which is equivalent to `fastfetch -s gpu --gpu-format '{2}'`
|
||||
. . which is equivalent to `fastfetch -s gpu --gpu-format '{name}'`
|
||||
|
||||
See `fastfetch -h format` for information on basic usage. For module specific formattion, see `fastfetch -h <module>-format`
|
||||
|
||||
@@ -175,6 +174,10 @@ pyfiglet -s -f small_slant $(fastfetch -s os --format json | jq -r '.[0].result.
|
||||
|
||||

|
||||
|
||||
### Q: My image logo behaves weird. How can I fix it?
|
||||
|
||||
See troubleshooting section: <https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options#troubleshooting>
|
||||
|
||||
### Q: Fastfetch runs in white and black on shell startup. Why?
|
||||
|
||||
This issue usually happens when using fastfetch with `p10k`. There are known incompatibility between fastfetch and p10k instant prompt.
|
||||
@@ -186,6 +189,53 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf
|
||||
|
||||
See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096).
|
||||
|
||||
### Q: Fastfetch shows less dpkg packages than neofetch, is it a bug?
|
||||
|
||||
Neofetch incorrectly counts `rc` packages ( the package has been removed, but that the configuration files remain ). Bug https://github.com/dylanaraps/neofetch/issues/2278
|
||||
|
||||
### Q: I use Debian / Ubuntu / Debian derived distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug?
|
||||
|
||||
Try upgrading `pci.ids`: Download <https://pci-ids.ucw.cz/v2.2/pci.ids> and overwrite file `/usr/share/hwdata/pci.ids`. For AMD GPUs, you should also upgrade `amdgpu.ids`: Download <https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids> and overwrite file `/usr/share/libdrm/amdgpu.ids`
|
||||
|
||||
Alternatively, you may try to use `fastfetch --gpu-driver-specific`, so that `fastfetch` will try to ask the driver for GPU name if supported.
|
||||
|
||||
### Q: I get error `Authorization required, but no authorization protocol specified` when running fastfetch in root
|
||||
|
||||
Try `export XAUTHORITY=$HOME/.Xauthority`
|
||||
|
||||
### Q: Fastfetch cannot detect my awesome 3rd-party macOS window manager!
|
||||
|
||||
Try `fastfetch --wm-detect-plugin`. See also [#984](https://github.com/fastfetch-cli/fastfetch/issues/984)
|
||||
|
||||
### Q: How can I change the colors of my ASCII logo?
|
||||
|
||||
Try `fastfetch --logo-color-[1-9] <color>`. `[1-9]` is the index of color placeholders.
|
||||
|
||||
For example: `fastfetch --logo-color-1 red --logo-color-2 green`.
|
||||
|
||||
In JSONC, you can use:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"logo": {
|
||||
"color": {
|
||||
"1": "red",
|
||||
"2": "green"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Q: How to hide a key?
|
||||
|
||||
Set the key to a white space.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"key": " "
|
||||
}
|
||||
```
|
||||
|
||||
### Q: I want feature A / B / C. Will fastfetch support it?
|
||||
|
||||
Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script:
|
||||
@@ -210,6 +260,13 @@ Otherwise, open a feature request in [GitHub Issues](https://github.com/fastfetc
|
||||
* For usage questions, please start a discussion in [GitHub Discussions](https://github.com/fastfetch-cli/fastfetch/discussions).
|
||||
* For possible bugs, please open an issue in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues). Be sure to fill the bug-report template carefully for developers to investigate.
|
||||
|
||||
## Donate
|
||||
|
||||
If you find Fastfetch to be useful, please consider donating.
|
||||
|
||||
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
|
||||
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
|
||||
|
||||
## Star History
|
||||
|
||||
Give it a star to support us!
|
||||
|
||||
@@ -183,7 +183,10 @@ __fastfetch_completion()
|
||||
"--display-precise-refresh-rate"
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-flags"
|
||||
"--localip-show-loop"
|
||||
"--localip-show-mtu"
|
||||
"--localip-show-speed"
|
||||
"--localip-name-prefix"
|
||||
"--localip-compact-type"
|
||||
"--escape-bedrock"
|
||||
|
||||
@@ -2,6 +2,11 @@ if not type -q fastfetch
|
||||
exit
|
||||
end
|
||||
|
||||
command -q python3
|
||||
if test $status -ne 0
|
||||
exit
|
||||
end
|
||||
|
||||
complete -c fastfetch -f
|
||||
|
||||
function __fastfetch_complete_bool
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#compdef fastfetch
|
||||
|
||||
function _fastfetch() {
|
||||
|
||||
whence python3 &> /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
local state
|
||||
|
||||
local -a opts=("${(f)$(
|
||||
@@ -19,7 +26,7 @@ def main():
|
||||
for flag in data[key]:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
for i in range(1, 10):
|
||||
command_prefix = f"--logo-color-{i}[{flag["desc"]} ({i})]"
|
||||
command_prefix = f"--logo-color-{i}[{flag['desc']} ({i})]"
|
||||
print_command(command_prefix, flag)
|
||||
continue
|
||||
|
||||
@@ -27,11 +34,11 @@ def main():
|
||||
continue
|
||||
|
||||
if "short" in flag:
|
||||
command_prefix = f"-{flag["short"]}[{flag["desc"]}]"
|
||||
command_prefix = f"-{flag['short']}[{flag['desc']}]"
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
if "long" in flag:
|
||||
command_prefix = f"--{flag["long"]}[{flag["desc"]}]"
|
||||
command_prefix = f"--{flag['long']}[{flag['desc']}]"
|
||||
print_command(command_prefix, flag)
|
||||
|
||||
|
||||
|
||||
Vendored
+96
@@ -1,3 +1,99 @@
|
||||
fastfetch (2.34.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.34.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 13 Jan 2025 16:06:22 +0800
|
||||
|
||||
fastfetch (2.34.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.34.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 09 Jan 2025 09:03:17 +0800
|
||||
|
||||
fastfetch (2.33.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.33.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 26 Dec 2024 09:42:27 +0800
|
||||
|
||||
fastfetch (2.32.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.32.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 18 Dec 2024 10:39:06 +0800
|
||||
|
||||
fastfetch (2.31.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.31.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 04 Dec 2024 08:41:40 +0800
|
||||
|
||||
fastfetch (2.30.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.30.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 18 Nov 2024 15:40:48 +0800
|
||||
|
||||
fastfetch (2.30.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.30.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 18 Nov 2024 09:30:58 +0800
|
||||
|
||||
fastfetch (2.29.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.29.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 04 Nov 2024 15:05:02 +0800
|
||||
|
||||
fastfetch (2.28.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.28.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 23 Oct 2024 10:18:59 +0800
|
||||
|
||||
fastfetch (2.27.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.27.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Sun, 06 Oct 2024 12:55:18 +0800
|
||||
|
||||
fastfetch (2.26.1ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Update correct code
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 30 Sep 2024 00:21:20 +0800
|
||||
|
||||
fastfetch (2.26.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.26.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Sun, 29 Sep 2024 16:15:31 +0800
|
||||
|
||||
fastfetch (2.26.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.26.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Sun, 29 Sep 2024 13:31:25 +0800
|
||||
|
||||
fastfetch (2.25.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.25.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 19 Sep 2024 10:28:38 +0800
|
||||
|
||||
fastfetch (2.24.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.24.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 11 Sep 2024 13:50:02 +0800
|
||||
|
||||
fastfetch (2.23.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.23.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 03 Sep 2024 18:44:11 +0800
|
||||
|
||||
fastfetch (2.22.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.22.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.22.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.34.1_source.buildinfo universe/utils optional
|
||||
|
||||
+1551
-354
File diff suppressed because it is too large
Load Diff
+12
-2
@@ -54,8 +54,12 @@
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
"battery",
|
||||
{
|
||||
"type": "battery",
|
||||
"temp": true
|
||||
},
|
||||
"poweradapter",
|
||||
"player",
|
||||
"media",
|
||||
@@ -66,7 +70,12 @@
|
||||
{
|
||||
"type": "localip",
|
||||
"showIpv6": true,
|
||||
"showMac": true
|
||||
"showMac": true,
|
||||
"showSpeed": true,
|
||||
"showMtu": true,
|
||||
"showLoop": true,
|
||||
"showFlags": true,
|
||||
"showAllIps": true
|
||||
},
|
||||
"dns",
|
||||
"wifi",
|
||||
@@ -91,6 +100,7 @@
|
||||
"type": "physicaldisk",
|
||||
"temp": true
|
||||
},
|
||||
"tpm",
|
||||
"version",
|
||||
"break",
|
||||
"colors"
|
||||
|
||||
+107
-97
@@ -1,100 +1,110 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
"stat": true,
|
||||
"pipe": true,
|
||||
"showErrors": true,
|
||||
"noBuffer": true
|
||||
},
|
||||
"logo": null,
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"os",
|
||||
"host",
|
||||
"bios",
|
||||
"bootmgr",
|
||||
"board",
|
||||
"chassis",
|
||||
"kernel",
|
||||
"initsystem",
|
||||
"uptime",
|
||||
"loadavg",
|
||||
"processes",
|
||||
"packages",
|
||||
"shell",
|
||||
"editor",
|
||||
"display",
|
||||
"brightness",
|
||||
"monitor",
|
||||
"lm",
|
||||
"de",
|
||||
"wm",
|
||||
"wmtheme",
|
||||
"theme",
|
||||
"icons",
|
||||
"font",
|
||||
"cursor",
|
||||
"wallpaper",
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
{
|
||||
"type": "cpu",
|
||||
"showPeCoreCount": true,
|
||||
"temp": true
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
"stat": true,
|
||||
"pipe": true,
|
||||
"showErrors": true,
|
||||
"noBuffer": true
|
||||
},
|
||||
"cpucache",
|
||||
"cpuusage",
|
||||
{
|
||||
"type": "gpu",
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
"disk",
|
||||
"zpool",
|
||||
"battery",
|
||||
"poweradapter",
|
||||
"player",
|
||||
"media",
|
||||
{
|
||||
"type": "publicip",
|
||||
"timeout": 1000
|
||||
},
|
||||
{
|
||||
"type": "localip",
|
||||
"showIpv6": true,
|
||||
"showMac": true
|
||||
},
|
||||
"dns",
|
||||
"wifi",
|
||||
"datetime",
|
||||
"locale",
|
||||
"vulkan",
|
||||
"opengl",
|
||||
"opencl",
|
||||
"users",
|
||||
"bluetooth",
|
||||
"bluetoothradio",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"netio",
|
||||
"diskio",
|
||||
{
|
||||
"type": "physicaldisk",
|
||||
"temp": true
|
||||
},
|
||||
"version",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
"logo": null,
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"os",
|
||||
"host",
|
||||
"bios",
|
||||
"bootmgr",
|
||||
"board",
|
||||
"chassis",
|
||||
"kernel",
|
||||
"initsystem",
|
||||
"uptime",
|
||||
"loadavg",
|
||||
"processes",
|
||||
"packages",
|
||||
"shell",
|
||||
"editor",
|
||||
"display",
|
||||
"brightness",
|
||||
"monitor",
|
||||
"lm",
|
||||
"de",
|
||||
"wm",
|
||||
"wmtheme",
|
||||
"theme",
|
||||
"icons",
|
||||
"font",
|
||||
"cursor",
|
||||
"wallpaper",
|
||||
"terminal",
|
||||
"terminalfont",
|
||||
"terminalsize",
|
||||
"terminaltheme",
|
||||
{
|
||||
"type": "cpu",
|
||||
"showPeCoreCount": true,
|
||||
"temp": true
|
||||
},
|
||||
"cpucache",
|
||||
"cpuusage",
|
||||
{
|
||||
"type": "gpu",
|
||||
"driverSpecific": true,
|
||||
"temp": true
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
{
|
||||
"type": "battery",
|
||||
"temp": true
|
||||
},
|
||||
"poweradapter",
|
||||
"player",
|
||||
"media",
|
||||
{
|
||||
"type": "publicip",
|
||||
"timeout": 1000
|
||||
},
|
||||
{
|
||||
"type": "localip",
|
||||
"showIpv6": true,
|
||||
"showMac": true,
|
||||
"showSpeed": true,
|
||||
"showMtu": true,
|
||||
"showLoop": true,
|
||||
"showFlags": true,
|
||||
"showAllIps": true
|
||||
},
|
||||
"dns",
|
||||
"wifi",
|
||||
"datetime",
|
||||
"locale",
|
||||
"vulkan",
|
||||
"opengl",
|
||||
"opencl",
|
||||
"users",
|
||||
// "bluetooth", // doesn't work on macOS because it requires bluetooth permissions
|
||||
// "bluetoothradio",
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
},
|
||||
"netio",
|
||||
"diskio",
|
||||
{
|
||||
"type": "physicaldisk",
|
||||
"temp": true
|
||||
},
|
||||
"tpm",
|
||||
"version",
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -119,9 +119,10 @@
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "monitor",
|
||||
"type": "display",
|
||||
"key": "MONITOR ({name})",
|
||||
"keyColor": "blue"
|
||||
"keyColor": "blue",
|
||||
"format": "{width}x{height} @ {refresh-rate} Hz - {physical-width}x{physical-height} mm ({inch} inches, {ppi} ppi)"
|
||||
},
|
||||
{
|
||||
"type": "custom", // DesignInfo
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"separator": "│ ",
|
||||
"percent": {
|
||||
"type": 6
|
||||
"type": ["bar", "hide-others"]
|
||||
},
|
||||
"bar": {
|
||||
"borderLeft": "",
|
||||
@@ -70,7 +70,7 @@
|
||||
"type": "localip",
|
||||
"key": "│ MAC ADDR │{$1}",
|
||||
"format": "{mac} ({ifname})",
|
||||
"showIPv4": false,
|
||||
"showIpv4": false,
|
||||
"showMac": true
|
||||
},
|
||||
{
|
||||
@@ -120,12 +120,18 @@
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│ MEMORY │{$1}",
|
||||
"format": "{used} / {total} [{percentage}]"
|
||||
"format": "{used} / {total} [{percentage}]",
|
||||
"percent": {
|
||||
"type": ["num"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│ USAGE │{$1}",
|
||||
"format": ""
|
||||
"format": "",
|
||||
"percent": {
|
||||
"type": ["bar", "hide-others"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
@@ -135,12 +141,18 @@
|
||||
"type": "disk",
|
||||
"key": "│ VOLUME │{$1}",
|
||||
"format": "{size-used} / {size-total} [{size-percentage}]",
|
||||
"folders": "/"
|
||||
"folders": "/",
|
||||
"percent": {
|
||||
"type": ["num"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│ DISK USAGE │{$1}",
|
||||
"format": ""
|
||||
"format": "",
|
||||
"percent": {
|
||||
"type": ["bar", "hide-others"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
// By jan-rex
|
||||
// Modified from: https://github.com/fastfetch-cli/fastfetch/discussions/1269
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"padding": {
|
||||
"top": 2
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": "",
|
||||
"constants": [
|
||||
// CONSTANT {$1} - COLOR BACKGROUND FOR KEY
|
||||
"\u001b[48;2;43;43;69m",
|
||||
// CONSTANT {$2} - COLOR BACKGROUND FOR OUTPUT
|
||||
"\u001b[48;2;56;59;78m",
|
||||
// CONSTANT {$3} - VERTICAL BARS AT START AND 75th CHARACTERS FORWARD AND BACKWARD
|
||||
"\u001b[90m│ │\u001b[60D\u001b[39m",
|
||||
]
|
||||
},
|
||||
"modules": [
|
||||
// CUSTOM - Top UI bar
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "{#90}{$1}╭─────────────╮",
|
||||
"format": "{#90}{$2}╭────────────────────────────────────────────────────────────╮",
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}{$1}│ {#92}User {#90}│",
|
||||
"format": "{$2}{$3}{user-name} {#2}[{home-dir}]"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"key": "{#90}{$1}│ {#92}Users {#90}│",
|
||||
"myselfOnly": false,
|
||||
"format": "{$2}{$3}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} {#2}[Login time: {login-time}]",
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "{#90}{$1}│ {#92}Datetime {#90}│",
|
||||
"format": "{$2}{$3}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} {#2}{weekday} {#2}[W{week}] {#2}[UTC{offset-from-utc}]"
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}{$1}│ {#93}Host: {#90}│",
|
||||
"format": "{$2}{$3}{#1}{#36}{host-name}"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": "{#90}{$1}│ {#93}Machine {#90}│",
|
||||
"format": "{$2}{$3}{name} {#2}{version}"
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "{#90}{$1}│ {#93}OS {#90}│",
|
||||
"format": "{$2}{$3}{pretty-name} {codename} {#2}[v{version}] {#2}[{arch}]"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "{#90}{$1}│ {#93}Kernel {#90}│",
|
||||
"format": "{$2}{$3}{sysname} {#2}[v{release}]"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "{#90}{$1}│ {#93}Uptime {#90}│",
|
||||
"format": "{$2}{$3}{?days}{days} Days + {?}{hours}:{minutes}:{seconds}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "{#90}{$1}│ {#91}CPU {#90}│",
|
||||
"showPeCoreCount": true,
|
||||
"temp": true,
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-types}] {#2}[{freq-max}]"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "{#90}{$1}│ {#91}GPU {#90}│",
|
||||
"detectionMethod": "auto",
|
||||
"driverSpecific": true,
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-count}] {#2}[{type}]"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "{#90}{$1}│ {#91}Memory {#90}│",
|
||||
"format": "{$2}{$3}{used} / {total} ({percentage}{$2})"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "{#90}{$1}│ {#91}Disk {#90}│",
|
||||
"format": "{$2}{$3}{size-used} / {size-total} ({size-percentage}{$2})"
|
||||
},
|
||||
{
|
||||
"type": "poweradapter",
|
||||
"key": "{#90}{$1}│ {#91}Power {#90}│",
|
||||
"format": "{$2}{$3}{name}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "{#90}{$1}│ {#95}Terminal {#90}│",
|
||||
"format": "{$2}{$3}{pretty-name} {#2}[{version}] [PID:{pid}]"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "{#90}{$1}│ {#95}Font {#90}│",
|
||||
"format": "{$2}{$3}{name} {#2}[{size}]"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "{#90}{$1}│ {#95}Shell {#90}│",
|
||||
"format": "{$2}{$3}{pretty-name} {#2}[v{version}] [PID:{pid}]"
|
||||
},
|
||||
{
|
||||
// localip IPv4
|
||||
"type": "localip",
|
||||
"key": "{#90}{$1}│ {#94}Local IPv4 {#90}│",
|
||||
"showPrefixLen": true,
|
||||
"showIpv4": true,
|
||||
"showIpv6": false,
|
||||
"showMtu": true,
|
||||
"format": "{$2}{$3}{ifname}: {ipv4} {#2}[MTU:{mtu}]"
|
||||
},
|
||||
{
|
||||
// localip IPv6
|
||||
"type": "localip",
|
||||
"key": "{#90}{$1}│ {#94}Local IPv6 {#90}│",
|
||||
"showPrefixLen": true,
|
||||
"showIpv4": false,
|
||||
"showIpv6": true,
|
||||
"showMtu": true,
|
||||
"format": "{$2}{$3}{ifname}: {ipv6} {#2}[MTU:{mtu}]"
|
||||
},
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "{#90}{$1}│ {#94}Public IPv4 {#90}│",
|
||||
"ipv6": false,
|
||||
"format": "{$2}{$3}{ip} {#2}[{location}]"
|
||||
},
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "{#90}{$1}│ {#94}Public IPv6 {#90}│",
|
||||
"ipv6": true,
|
||||
"format": "{$2}{$3}{ip} {#2}[{location}]"
|
||||
},
|
||||
// CUSTOM - Button UI bar
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "{#90}{$1}╰─────────────╯",
|
||||
"format": "{#90}{$2}╰────────────────────────────────────────────────────────────╯",
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -25,7 +25,10 @@
|
||||
"type": "disk",
|
||||
"folders": "/"
|
||||
},
|
||||
"battery",
|
||||
{
|
||||
"type": "battery",
|
||||
"key": "Battery"
|
||||
},
|
||||
{
|
||||
"type": "colors",
|
||||
"paddingLeft": 10,
|
||||
|
||||
@@ -5,18 +5,22 @@ set -e
|
||||
mkdir -p build/
|
||||
cd build/
|
||||
|
||||
if [ -z "${CMAKE_BUILD_TYPE}" ]; then
|
||||
CMAKE_BUILD_TYPE=Release
|
||||
fi
|
||||
cmake "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" ..
|
||||
cmake ..
|
||||
|
||||
if [ -z "$OSTYPE" ] || [ "$OSTYPE" = "linux-gnu" ]; then
|
||||
cmake_build_args="-j$(nproc)"
|
||||
elif [ "$OSTYPE" = "darwin" ]; then
|
||||
cmake_build_args="-j$(sysctl -n hw.ncpu)"
|
||||
else
|
||||
cmake_build_args=""
|
||||
fi
|
||||
cmake --build . --target fastfetch ${cmake_build_args}
|
||||
kernel_name="$(uname -s)"
|
||||
|
||||
case "${kernel_name}" in
|
||||
"Linux" | "MINGW"*)
|
||||
cmake_build_args="-j$(nproc)"
|
||||
;;
|
||||
"Darwin" | *"BSD" | "DragonFly")
|
||||
cmake_build_args="-j$(sysctl -n hw.ncpu)"
|
||||
;;
|
||||
*)
|
||||
cmake_build_args=""
|
||||
;;
|
||||
esac
|
||||
|
||||
cmake --build . --target fastfetch "${cmake_build_args}"
|
||||
|
||||
./fastfetch "$@"
|
||||
|
||||
Executable
+258
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Python script to generate a man page for the command `fastfetch`.
|
||||
The man content will be printed to stdout so you will need to
|
||||
pipe it to a file if you want to save it.
|
||||
The command options will be generated using a JSON file.
|
||||
For the format of the JSON file, see https://github.com/fastfetch-cli/fastfetch/blob/dev/src/data/help.json
|
||||
"""
|
||||
|
||||
from json import load
|
||||
from datetime import datetime, timezone
|
||||
from time import time
|
||||
from re import search
|
||||
from os import environ, path
|
||||
|
||||
|
||||
###### Text Decorations Tags ######
|
||||
|
||||
startUnderline = r"\fI" # start underline text tag
|
||||
endUnderline = r"\fR" # end underline text tag
|
||||
|
||||
startBold = r"\fB" # start bold text tag
|
||||
endBold = r"\fR" # end bold text tag
|
||||
|
||||
|
||||
###### Parameters ######
|
||||
|
||||
# path to the current directory
|
||||
pathToCurrentDir = path.dirname(__file__)
|
||||
# path to the JSON option file
|
||||
pathToHelpFile = path.join(pathToCurrentDir, "../src/data/help.json")
|
||||
# man page section
|
||||
manSection = 1
|
||||
# title (center header)
|
||||
titlePage = "Fastfetch man page"
|
||||
# date (center footer)
|
||||
# format : "Month (abbreviation) Day Year"
|
||||
todayDate = datetime.fromtimestamp(
|
||||
int(environ.get("SOURCE_DATE_EPOCH", time())),
|
||||
tz=timezone.utc,
|
||||
).strftime("%b %d %Y")
|
||||
# file to fastfetch version (left footer)
|
||||
pathToVersionFile = path.join(pathToCurrentDir, "../CMakeLists.txt")
|
||||
|
||||
|
||||
###### Sections Text ######
|
||||
|
||||
# text displayed in the "NAME" section
|
||||
nameSection = r"fastfetch \- A maintained, feature\-rich and performance oriented, neofetch like system information tool"
|
||||
|
||||
# text displayed at the beginning of the "OPTIONS" section
|
||||
optionSection = r"""
|
||||
Parsing is not case sensitive. E.g. \fB--logo-type\fR is
|
||||
equal to \fB--LOGO-TYPE\fR.
|
||||
|
||||
If a value is between square brackets, it is optional.
|
||||
An optional boolean value defaults to true if not specified.
|
||||
|
||||
More detailed help messages for each options can be printed
|
||||
with \fB-h <option_without_dash_prefix>\fR.
|
||||
|
||||
All options can be made permanent with command
|
||||
\fBfastfetch <options> --gen-config\fR.
|
||||
"""
|
||||
|
||||
# text displayed in the "CONFIGURATION"
|
||||
configurationSection = f"""
|
||||
.SS Fetch Structure
|
||||
|
||||
The structure of a fetch describes the modules that should
|
||||
be included in the output. It consists of a string of modules,
|
||||
separated by a colon (:). To list all available modules,
|
||||
use --list-modules.
|
||||
|
||||
|
||||
.SS Config Files
|
||||
|
||||
Fastfetch uses JSONC based format for configuration.
|
||||
Fastfetch doesn't generate config file automatically;
|
||||
it should be generated manually by {startBold}--gen-config{endBold}.
|
||||
The config file will be saved in
|
||||
{startBold}~/.config/fastfetch/config.jsonc{endBold} by default.
|
||||
|
||||
A JSONC config file is a JSON file that also supports comments
|
||||
with (// and /* */). Those files must have the extension '.jsonc'.
|
||||
|
||||
The specified configuration/preset files are searched in the following order:
|
||||
|
||||
{startBold}1.{endBold} relative to the current working directory
|
||||
|
||||
{startBold}2.{endBold} relative to ~/.local/share/fastfetch/presets/
|
||||
|
||||
{startBold}3.{endBold} relative to /usr/share/fastfetch/presets/
|
||||
|
||||
Fastfetch provides some default presets. List them with --list-presets.
|
||||
"""
|
||||
|
||||
# text displayed in the "EXAMPLE" section
|
||||
exampleSection = """
|
||||
.SS Config files:
|
||||
.nf
|
||||
// ~/.config/fastfetch/config.jsonc
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"module1",
|
||||
{
|
||||
"type": "module2",
|
||||
"module2-option": "value"
|
||||
}
|
||||
]
|
||||
}
|
||||
.fi
|
||||
"""
|
||||
|
||||
# text displayed in the "BUGS" section
|
||||
bugSection = "Please report bugs to : \
|
||||
https://github.com/fastfetch-cli/fastfetch/issues"
|
||||
|
||||
# text displayed in the "WIKI" section
|
||||
wikiSection = "Fastfetch github wiki : https://github.com/fastfetch-cli/fastfetch/wiki/Configuration"
|
||||
|
||||
|
||||
###### Argument decoration ######
|
||||
|
||||
### optional arguments tags ###
|
||||
|
||||
# if an optional argument is displayed as [?optArg] (with "optArg" underlined)
|
||||
# this value should be f"[?{startUnderline}"
|
||||
startOptionalArgument = f"[{startUnderline}?"
|
||||
# if an optional argument is displayed as [?optArg] (with "optArg underlined")
|
||||
# this value should be f"{endUnderline}]"
|
||||
endOptionalArgument = f"{endUnderline}]"
|
||||
|
||||
### mandatory arguments tags ###
|
||||
startMandatoryArgument = f"{startUnderline}"
|
||||
endMandatoryArgument = f"{endUnderline}"
|
||||
|
||||
def main():
|
||||
|
||||
# importing the JSON file
|
||||
with open(pathToHelpFile, 'r') as jsonFile:
|
||||
helpFileData = load(jsonFile) # json.load
|
||||
|
||||
|
||||
######## Start printing the generated .1 file ########
|
||||
|
||||
|
||||
###### header, footer & config #####
|
||||
|
||||
print(f".TH FASTFETCH {manSection} ", end=" ")
|
||||
print(f"\"{todayDate}\"", end=" ")
|
||||
|
||||
# version number
|
||||
with open(pathToVersionFile, 'r') as versionFile:
|
||||
|
||||
# research version number in file with regex
|
||||
for line in versionFile:
|
||||
researchVersion = search(r"^\s*VERSION (\d+\.\d+\.\d+)$", line)
|
||||
if (researchVersion):
|
||||
print(f"\"{researchVersion.group(1)}\"", end=" ")
|
||||
break
|
||||
|
||||
print(f"\"{titlePage}\"")
|
||||
|
||||
|
||||
###### Name ######
|
||||
|
||||
print(".SH NAME")
|
||||
print(nameSection)
|
||||
|
||||
|
||||
##### Synopsis ######
|
||||
|
||||
print(".SH SYNOPSIS")
|
||||
print(".B fastfetch")
|
||||
print(f"[{startUnderline}OPTIONS{endUnderline}]")\
|
||||
|
||||
|
||||
###### Wiki ######
|
||||
|
||||
print(".SH WIKI")
|
||||
print(wikiSection)
|
||||
|
||||
|
||||
###### Configuration ######
|
||||
|
||||
print(".SH CONFIGURATION")
|
||||
print(configurationSection)
|
||||
|
||||
|
||||
###### Options ######
|
||||
|
||||
print(".SH OPTIONS")
|
||||
print(optionSection)
|
||||
print()
|
||||
|
||||
# loop through every options sections
|
||||
for key, value in helpFileData.items():
|
||||
|
||||
# print new subsection
|
||||
print(f".SS {key}:")
|
||||
|
||||
# loop through every option in a section
|
||||
for option in value:
|
||||
# list of existing keys for this option
|
||||
keyList = option.keys()
|
||||
|
||||
# start a new "option" entry
|
||||
print(".TP")
|
||||
print(startBold, end="")
|
||||
|
||||
# short option (-opt)
|
||||
if "short" in keyList:
|
||||
print(fr"\-{ option['short'] }", end="")
|
||||
# if also have a long option, print a comma
|
||||
if "long" in keyList:
|
||||
print(", ", end="")
|
||||
|
||||
# long option (--option)
|
||||
if "long" in keyList:
|
||||
print(fr"\-\-{ option['long'] }", end="")
|
||||
|
||||
print(endBold, end=" ")
|
||||
|
||||
# arguments
|
||||
if "arg" in keyList:
|
||||
# if argument is optional, print "[arg]"
|
||||
if "optional" in option["arg"].keys() and option["arg"]["optional"]:
|
||||
print(startOptionalArgument + option['arg']['type'] + endOptionalArgument, end="")
|
||||
|
||||
# if argument is mandatory, print "arg"
|
||||
else:
|
||||
print(startMandatoryArgument + option['arg']['type'] + endMandatoryArgument, end="")
|
||||
|
||||
# description
|
||||
print(f"\n {option['desc']} \n")
|
||||
|
||||
|
||||
###### Examples ######
|
||||
|
||||
print(".SH EXAMPLES")
|
||||
print(exampleSection)
|
||||
|
||||
|
||||
###### Bugs ######
|
||||
|
||||
print(".SH BUGS")
|
||||
print(bugSection)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+97
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from requests import get as http_get
|
||||
|
||||
class PciDeviceModel:
|
||||
def __init__(self, id: int, name: str):
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
||||
class PciVendorModel:
|
||||
def __init__(self, id: int, name: str):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.devices = []
|
||||
|
||||
def main(keep_vendor_list: set):
|
||||
vendors = []
|
||||
try:
|
||||
with open('pci.ids', 'r') as f:
|
||||
full_text = f.read()
|
||||
except FileNotFoundError:
|
||||
response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids')
|
||||
full_text = response.text
|
||||
|
||||
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
|
||||
for line in dev_list_text.split('\n'):
|
||||
if not line or line[0] == '#':
|
||||
continue
|
||||
if line[0] != '\t':
|
||||
id, name = line.split(' ', maxsplit=1)
|
||||
vendors.append(PciVendorModel(int(id, 16), name))
|
||||
elif line[1] != '\t':
|
||||
id, name = line[1:].split(' ', maxsplit=1)
|
||||
vendors[-1].devices.append(PciDeviceModel(int(id, 16), name))
|
||||
|
||||
code = """\
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// https://opensource.org/license/BSD-3-Clause
|
||||
// Generated from https://pci-ids.ucw.cz/v2.2/pci.ids
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct FFPciDevice
|
||||
{
|
||||
const uint32_t id;
|
||||
const char* name;
|
||||
} FFPciDevice;
|
||||
|
||||
typedef struct FFPciVendor
|
||||
{
|
||||
const uint32_t id;
|
||||
const char* name;
|
||||
const FFPciDevice* devices;
|
||||
const uint32_t nDevices;
|
||||
} FFPciVendor;
|
||||
"""
|
||||
|
||||
if keep_vendor_list:
|
||||
vendors = [vendor for vendor in vendors if vendor.id in keep_vendor_list]
|
||||
|
||||
for vendor in vendors:
|
||||
if vendor.devices:
|
||||
piece = ',\n '.join('{{ 0x{:04X}, "{}" }}'.format(device.id, device.name.replace('"', '\\"')) for device in vendor.devices)
|
||||
code += f"""
|
||||
// {vendor.name}
|
||||
static const FFPciDevice pciDevices_{vendor.id:04X}[] = {{
|
||||
{piece},
|
||||
{{}},
|
||||
}};
|
||||
"""
|
||||
|
||||
piece = ',\n '.join('{{ 0x{:04X}, "{}", {}, {} }}'.format(vendor.id, vendor.name.replace('"', '\\"'), vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL", len(vendor.devices)) for vendor in vendors)
|
||||
code += f"""
|
||||
const FFPciVendor ffPciVendors[] = {{
|
||||
{piece},
|
||||
{{}},
|
||||
}};"""
|
||||
|
||||
print(code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# From <src/detection/gpu/gpu.c>
|
||||
main({
|
||||
0x106b, # Apple
|
||||
0x1002, 0x1022, # AMD
|
||||
0x8086, 0x8087, 0x03e7, # Intel
|
||||
0x0955, 0x10de, 0x12d2, # Nvidia
|
||||
0x1ed5, # MThreads
|
||||
0x5143, # Qualcomm
|
||||
0x14c3, # MTK
|
||||
0x15ad, # VMware
|
||||
0x1af4, # RedHat
|
||||
0x1ab8, # Parallel
|
||||
0x1414, # Microsoft
|
||||
0x108e, # Oracle
|
||||
})
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
|
||||
static bool loadLibSymbols(FFDBusLibrary* lib)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dbus, &instance.config.library.libDBus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(dbus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_append_args, false)
|
||||
@@ -171,7 +171,7 @@ DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const c
|
||||
if (arg)
|
||||
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
@@ -189,7 +189,7 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
DBUS_TYPE_STRING, &property,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, FF_DBUS_TIMEOUT_MILLISECONDS, NULL);
|
||||
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
|
||||
|
||||
dbus->lib->ffdbus_message_unref(message);
|
||||
|
||||
|
||||
+5
-2
@@ -6,8 +6,6 @@
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/library.h"
|
||||
|
||||
#define FF_DBUS_TIMEOUT_MILLISECONDS 100
|
||||
|
||||
typedef struct FFDBusLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(dbus_bus_get)
|
||||
@@ -38,4 +36,9 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
|
||||
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
|
||||
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
|
||||
|
||||
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
|
||||
{
|
||||
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface);
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_DBUS
|
||||
|
||||
+5
-5
@@ -51,7 +51,7 @@ static void fontInitPretty(FFfont* font)
|
||||
|
||||
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||
{
|
||||
ffStrbufAppend(&font->pretty, ffListGet(&font->styles, i));
|
||||
ffStrbufAppend(&font->pretty, FF_LIST_GET(FFstrbuf, font->styles, i));
|
||||
|
||||
if(i < font->styles.length - 1)
|
||||
ffStrbufAppendS(&font->pretty, ", ");
|
||||
@@ -86,7 +86,7 @@ void ffFontInitQt(FFfont* font, const char* data)
|
||||
{
|
||||
do
|
||||
{
|
||||
FFstrbuf* style = ffListAdd(&font->styles);
|
||||
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(style);
|
||||
data = ffStrbufAppendSUntilC(style, data, ' ');
|
||||
if (data) data++;
|
||||
@@ -142,7 +142,7 @@ static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* altern
|
||||
) {
|
||||
if(alternativeBuffer == NULL)
|
||||
{
|
||||
alternativeBuffer = ffListAdd(&font->styles);
|
||||
alternativeBuffer = (FFstrbuf*) ffListAdd(&font->styles);
|
||||
ffStrbufInit(alternativeBuffer);
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ void ffFontDestroy(FFfont* font)
|
||||
ffStrbufDestroy(&font->name);
|
||||
ffStrbufDestroy(&font->size);
|
||||
|
||||
for(uint32_t i = 0; i < font->styles.length; i++)
|
||||
ffStrbufDestroy(ffListGet(&font->styles, i));
|
||||
FF_LIST_FOR_EACH(FFstrbuf, str, font->styles)
|
||||
ffStrbufDestroy(str);
|
||||
ffListDestroy(&font->styles);
|
||||
}
|
||||
|
||||
+127
-84
@@ -8,39 +8,53 @@
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
{
|
||||
if(formatarg->type == FF_FORMAT_ARG_TYPE_INT)
|
||||
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)
|
||||
ffStrbufAppendF(buffer, "%" PRIu8, *(uint8_t*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRING)
|
||||
ffStrbufAppendS(buffer, (const char*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_STRBUF)
|
||||
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_FLOAT)
|
||||
ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_DOUBLE)
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_BOOL)
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
else if(formatarg->type == FF_FORMAT_ARG_TYPE_LIST)
|
||||
switch(formatarg->type)
|
||||
{
|
||||
const FFlist* list = formatarg->value;
|
||||
for(uint32_t i = 0; i < list->length; i++)
|
||||
case FF_FORMAT_ARG_TYPE_INT:
|
||||
ffStrbufAppendF(buffer, "%" PRIi32, *(int32_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT:
|
||||
ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT64:
|
||||
ffStrbufAppendF(buffer, "%" PRIu64, *(uint64_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT16:
|
||||
ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_UINT8:
|
||||
ffStrbufAppendF(buffer, "%" PRIu8, *(uint8_t*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_STRING:
|
||||
ffStrbufAppendS(buffer, (const char*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_STRBUF:
|
||||
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_FLOAT:
|
||||
ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_DOUBLE:
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_BOOL:
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_LIST:
|
||||
{
|
||||
ffStrbufAppend(buffer, ffListGet(list, i));
|
||||
if(i < list->length - 1)
|
||||
ffStrbufAppendS(buffer, ", ");
|
||||
const FFlist* list = (const FFlist*) formatarg->value;
|
||||
for(uint32_t i = 0; i < list->length; i++)
|
||||
{
|
||||
ffStrbufAppend(buffer, FF_LIST_GET(FFstrbuf, *list, i));
|
||||
if(i < list->length - 1)
|
||||
ffStrbufAppendS(buffer, ", ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(formatarg->type != FF_FORMAT_ARG_TYPE_NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type);
|
||||
default:
|
||||
if(formatarg->type != FF_FORMAT_ARG_TYPE_NULL)
|
||||
fprintf(stderr, "Error: format string \"%s\": argument is not implemented: %i\n", buffer->chars, formatarg->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +110,12 @@ static inline bool formatArgSet(const FFformatarg* arg)
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_INT && *(int*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRBUF && ((FFstrbuf*)arg->value)->length > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet(arg->value)) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_STRING && ffStrSet((char*)arg->value)) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT8 && *(uint8_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT16 && *(uint16_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_UINT && *(uint32_t*)arg->value > 0) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && arg->value != NULL)
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_BOOL && *(bool*)arg->value) ||
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_LIST && ((FFlist*)arg->value)->length > 0)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -265,34 +280,18 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t truncLength = 0;
|
||||
char align = '\0';
|
||||
char* pSep = memchr(placeholderValue.chars, ':', placeholderValue.length);
|
||||
if (pSep)
|
||||
align = ':';
|
||||
char* pSep = placeholderValue.chars;
|
||||
char cSep = '\0';
|
||||
while (*pSep && *pSep != ':' && *pSep != '<' && *pSep != '>' && *pSep != '~')
|
||||
++pSep;
|
||||
if (*pSep)
|
||||
{
|
||||
cSep = *pSep;
|
||||
*pSep = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pSep = memchr(placeholderValue.chars, '<', placeholderValue.length);
|
||||
if (pSep)
|
||||
align = '<';
|
||||
else
|
||||
{
|
||||
pSep = memchr(placeholderValue.chars, '>', placeholderValue.length);
|
||||
if (pSep)
|
||||
align = '>';
|
||||
}
|
||||
}
|
||||
|
||||
if (pSep)
|
||||
{
|
||||
char* pEnd = NULL;
|
||||
truncLength = (int32_t) strtol(pSep + 1, &pEnd, 10);
|
||||
if (*pEnd != '\0')
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
*pSep = '\0';
|
||||
pSep = NULL;
|
||||
}
|
||||
|
||||
uint32_t index = getArgumentIndex(placeholderValue.chars, numArgs, arguments);
|
||||
@@ -303,53 +302,97 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
|
||||
if (index > numArgs)
|
||||
{
|
||||
if (pSep) *pSep = align;
|
||||
if (pSep) *pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ellipsis = false;
|
||||
if (truncLength < 0)
|
||||
{
|
||||
ellipsis = true;
|
||||
truncLength = -truncLength;
|
||||
}
|
||||
|
||||
if (!align)
|
||||
if (!cSep)
|
||||
ffFormatAppendFormatArg(buffer, &arguments[index - 1]);
|
||||
else if (cSep == '~')
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY tempString = ffStrbufCreate();
|
||||
ffFormatAppendFormatArg(&tempString, &arguments[index - 1]);
|
||||
|
||||
char* pEnd = NULL;
|
||||
int32_t start = (int32_t) strtol(pSep + 1, &pEnd, 10);
|
||||
if (start < 0)
|
||||
start = (int32_t) tempString.length + start;
|
||||
if (start >= 0 && (uint32_t) start < tempString.length)
|
||||
{
|
||||
if (*pEnd == '\0')
|
||||
ffStrbufAppendNS(buffer, tempString.length - (uint32_t) start, &tempString.chars[start]);
|
||||
else if (*pEnd == ',')
|
||||
{
|
||||
int32_t end = (int32_t) strtol(pEnd + 1, &pEnd, 10);
|
||||
if (!*pEnd)
|
||||
{
|
||||
if (end < 0)
|
||||
end = (int32_t) tempString.length + end;
|
||||
if ((uint32_t) end > tempString.length)
|
||||
end = (int32_t) tempString.length;
|
||||
if (end > start)
|
||||
ffStrbufAppendNS(buffer, (uint32_t) (end - start), &tempString.chars[start]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*pEnd)
|
||||
{
|
||||
*pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufClear(&placeholderValue);
|
||||
ffFormatAppendFormatArg(&placeholderValue, &arguments[index - 1]);
|
||||
if (placeholderValue.length == (uint32_t) truncLength)
|
||||
ffStrbufAppend(buffer, &placeholderValue);
|
||||
else if (placeholderValue.length > (uint32_t) truncLength)
|
||||
char* pEnd = NULL;
|
||||
int32_t truncLength = (int32_t) strtol(pSep + 1, &pEnd, 10);
|
||||
if (*pEnd != '\0')
|
||||
{
|
||||
if (align == ':')
|
||||
*pSep = cSep;
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ellipsis = false;
|
||||
if (truncLength < 0)
|
||||
{
|
||||
ellipsis = true;
|
||||
truncLength = -truncLength;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tempString = ffStrbufCreate();
|
||||
ffFormatAppendFormatArg(&tempString, &arguments[index - 1]);
|
||||
if (tempString.length == (uint32_t) truncLength)
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
else if (tempString.length > (uint32_t) truncLength)
|
||||
{
|
||||
if (cSep == ':')
|
||||
{
|
||||
ffStrbufSubstrBefore(&placeholderValue, (uint32_t) truncLength);
|
||||
ffStrbufTrimRightSpace(&placeholderValue);
|
||||
ffStrbufSubstrBefore(&tempString, (uint32_t) truncLength);
|
||||
ffStrbufTrimRightSpace(&tempString);
|
||||
}
|
||||
else
|
||||
ffStrbufSubstrBefore(&placeholderValue, (uint32_t) (!ellipsis? truncLength : truncLength - 1));
|
||||
ffStrbufAppend(buffer, &placeholderValue);
|
||||
ffStrbufSubstrBefore(&tempString, (uint32_t) (!ellipsis? truncLength : truncLength - 1));
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
|
||||
if (ellipsis)
|
||||
ffStrbufAppendS(buffer, "…");
|
||||
}
|
||||
else if (align == ':')
|
||||
ffStrbufAppend(buffer, &placeholderValue);
|
||||
else if (cSep == ':')
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
else
|
||||
{
|
||||
if (align == '<')
|
||||
if (cSep == '<')
|
||||
{
|
||||
ffStrbufAppend(buffer, &placeholderValue);
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - placeholderValue.length, ' ');
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - tempString.length, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - placeholderValue.length, ' ');
|
||||
ffStrbufAppend(buffer, &placeholderValue);
|
||||
ffStrbufAppendNC(buffer, (uint32_t) truncLength - tempString.length, ' ');
|
||||
ffStrbufAppend(buffer, &tempString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+20
-7
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "util/FFstrbuf.h"
|
||||
|
||||
typedef enum FFformatargtype
|
||||
typedef enum __attribute__((__packed__)) FFformatArgType
|
||||
{
|
||||
FF_FORMAT_ARG_TYPE_NULL = 0,
|
||||
FF_FORMAT_ARG_TYPE_UINT,
|
||||
@@ -16,18 +16,31 @@ typedef enum FFformatargtype
|
||||
FF_FORMAT_ARG_TYPE_DOUBLE,
|
||||
FF_FORMAT_ARG_TYPE_LIST,
|
||||
FF_FORMAT_ARG_TYPE_BOOL
|
||||
} FFformatargtype;
|
||||
} FFformatArgType;
|
||||
|
||||
#define FF_FORMAT_ARG(variable, var_name) { _Generic((variable), \
|
||||
uint32_t: FF_FORMAT_ARG_TYPE_UINT, \
|
||||
uint64_t: FF_FORMAT_ARG_TYPE_UINT64, \
|
||||
uint16_t: FF_FORMAT_ARG_TYPE_UINT16, \
|
||||
uint8_t: FF_FORMAT_ARG_TYPE_UINT8, \
|
||||
int32_t: FF_FORMAT_ARG_TYPE_INT, \
|
||||
char*: FF_FORMAT_ARG_TYPE_STRING, \
|
||||
const char*: FF_FORMAT_ARG_TYPE_STRING, \
|
||||
FFstrbuf: FF_FORMAT_ARG_TYPE_STRBUF, \
|
||||
float: FF_FORMAT_ARG_TYPE_FLOAT, \
|
||||
double: FF_FORMAT_ARG_TYPE_DOUBLE, \
|
||||
FFlist: FF_FORMAT_ARG_TYPE_LIST, \
|
||||
bool: FF_FORMAT_ARG_TYPE_BOOL \
|
||||
), _Generic((variable), char*: (variable), const char*: (variable), default: &(variable) ), (var_name) }
|
||||
|
||||
typedef struct FFformatarg
|
||||
{
|
||||
FFformatargtype type;
|
||||
FFformatArgType type;
|
||||
const void* value;
|
||||
const char* name; // argument name, must start with an alphabet
|
||||
} FFformatarg;
|
||||
|
||||
void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg);
|
||||
void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffParseFormatString((buffer), (formatstr), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
#define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, arguments) \
|
||||
ffParseFormatString((buffer), (formatstr), sizeof(arguments) / sizeof(*arguments), (arguments));
|
||||
|
||||
+14
-13
@@ -43,7 +43,6 @@ static void defaultConfig(void)
|
||||
ffOptionsInitGeneral(&instance.config.general);
|
||||
ffOptionsInitModules(&instance.config.modules);
|
||||
ffOptionsInitDisplay(&instance.config.display);
|
||||
ffOptionsInitLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
void ffInitInstance(void)
|
||||
@@ -77,19 +76,21 @@ static void resetConsole(void)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL WINAPI consoleHandler(DWORD signal)
|
||||
BOOL WINAPI consoleHandler(FF_MAYBE_UNUSED DWORD signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
static void exitSignalHandler(int signal)
|
||||
static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
FF_UNUSED(signal);
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
// empty; used to interrupt the poll and read syscalls
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffStart(void)
|
||||
@@ -119,6 +120,7 @@ void ffStart(void)
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
@@ -148,7 +150,6 @@ static void destroyConfig(void)
|
||||
ffOptionsDestroyGeneral(&instance.config.general);
|
||||
ffOptionsDestroyModules(&instance.config.modules);
|
||||
ffOptionsDestroyDisplay(&instance.config.display);
|
||||
ffOptionsDestroyLibrary(&instance.config.library);
|
||||
}
|
||||
|
||||
static void destroyState(void)
|
||||
@@ -181,18 +182,15 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_XCB_RANDR
|
||||
"xcb-randr\n"
|
||||
#endif
|
||||
#if FF_HAVE_XCB
|
||||
"xcb\n"
|
||||
#endif
|
||||
#if FF_HAVE_XRANDR
|
||||
"xrandr\n"
|
||||
#endif
|
||||
#if FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
#if FF_HAVE_DRM
|
||||
"drm\n"
|
||||
#endif
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
"drm_amdgpu\n"
|
||||
#endif
|
||||
#if FF_HAVE_GIO
|
||||
"gio\n"
|
||||
#endif
|
||||
@@ -244,7 +242,7 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_DDCUTIL
|
||||
"libddcutil\n"
|
||||
#endif
|
||||
#if FF_HAVE_ELF
|
||||
#if FF_HAVE_ELF || __sun || (__FreeBSD__ && !__DragonFly__) || __OpenBSD__ || __NetBSD__
|
||||
"libelf\n"
|
||||
#endif
|
||||
#if FF_HAVE_LIBZFS
|
||||
@@ -262,6 +260,9 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_LINUX_WIRELESS
|
||||
"linux/wireless\n"
|
||||
#endif
|
||||
#if FF_HAVE_EMBEDDED_PCIIDS
|
||||
"Embedded pciids\n"
|
||||
#endif
|
||||
""
|
||||
, stdout);
|
||||
}
|
||||
|
||||
+38
-3
@@ -13,6 +13,8 @@
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
typedef int FFNativeFD;
|
||||
#define FF_INVALID_FD (-1)
|
||||
// procfs's file can be changed between read calls such as /proc/meminfo and /proc/uptime.
|
||||
@@ -66,9 +68,11 @@ static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data)
|
||||
}
|
||||
|
||||
ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data);
|
||||
ssize_t ffReadFileDataRelative(FFNativeFD dfd, const char* fileName, size_t dataSize, void* data);
|
||||
|
||||
bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer);
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
@@ -76,12 +80,19 @@ static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFileBuffer(fileName, buffer);
|
||||
}
|
||||
|
||||
static inline bool ffReadFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFileBufferRelative(dfd, fileName, buffer);
|
||||
}
|
||||
|
||||
//Bit flags, combine with |
|
||||
typedef enum FFPathType
|
||||
typedef enum __attribute__((__packed__)) FFPathType
|
||||
{
|
||||
FF_PATHTYPE_FILE = 1 << 0,
|
||||
FF_PATHTYPE_DIRECTORY = 1 << 1,
|
||||
FF_PATHTYPE_ANY = FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY,
|
||||
FF_PATHTYPE_FORCE_UNSIGNED = UINT8_MAX,
|
||||
} FFPathType;
|
||||
|
||||
static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
@@ -108,6 +119,7 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if __APPLE__ // #1395
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
@@ -119,6 +131,24 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
|
||||
if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR)
|
||||
return true;
|
||||
#else
|
||||
size_t len = strlen(path);
|
||||
assert(len < PATH_MAX);
|
||||
if (len == 0) return false;
|
||||
|
||||
int ret;
|
||||
if (path[len - 1] != '/')
|
||||
{
|
||||
char buf[PATH_MAX + 1];
|
||||
memcpy(buf, path, len);
|
||||
buf[len] = '/';
|
||||
buf[len + 1] = 0;
|
||||
ret = access(buf, F_OK);
|
||||
}
|
||||
else
|
||||
ret = access(path, F_OK);
|
||||
return pathType == FF_PATHTYPE_DIRECTORY ? ret == 0 : ret == -1 && errno == ENOTDIR;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -130,8 +160,8 @@ 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, ...);
|
||||
FF_C_SCANF(3, 4)
|
||||
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...);
|
||||
|
||||
// Not thread safe!
|
||||
bool ffSuppressIO(bool suppress);
|
||||
@@ -211,3 +241,8 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char*
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Only O_RDONLY is supported
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
|
||||
#endif
|
||||
|
||||
+91
-17
@@ -1,17 +1,25 @@
|
||||
#include "io.h"
|
||||
#include "fastfetch.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#ifndef __APPLE__
|
||||
#include <poll.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_WORDEXP
|
||||
#include <wordexp.h>
|
||||
#elif FF_HAVE_GLOB
|
||||
#warning "<wordexp.h> is not available, use <glob.h> instead"
|
||||
#include <glob.h>
|
||||
#else
|
||||
#warning "<wordexp.h> not available"
|
||||
#warning "Neither <wordexp.h> nor <glob.h> is available"
|
||||
#endif
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
@@ -30,7 +38,7 @@ static void createSubfolders(const char* fileName)
|
||||
bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||
{
|
||||
int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC;
|
||||
int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
mode_t openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
|
||||
int FF_AUTO_CLOSE_FD fd = open(fileName, openFlagsModes, openFlagsRights);
|
||||
if(fd == -1)
|
||||
@@ -101,6 +109,15 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data)
|
||||
return ffReadFDData(fd, dataSize, data);
|
||||
}
|
||||
|
||||
ssize_t ffReadFileDataRelative(int dfd, const char* fileName, size_t dataSize, void* data)
|
||||
{
|
||||
int FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, O_RDONLY | O_CLOEXEC);
|
||||
if(fd == -1)
|
||||
return -1;
|
||||
|
||||
return ffReadFDData(fd, dataSize, data);
|
||||
}
|
||||
|
||||
bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY | O_CLOEXEC);
|
||||
@@ -110,6 +127,15 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
bool ffAppendFileBufferRelative(int dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
int FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, O_RDONLY | O_CLOEXEC);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -117,17 +143,31 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o
|
||||
#if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056
|
||||
|
||||
wordexp_t exp;
|
||||
if(wordexp(in, &exp, 0) != 0)
|
||||
if (wordexp(in, &exp, 0) != 0)
|
||||
return false;
|
||||
|
||||
if (exp.we_wordc == 1)
|
||||
if (exp.we_wordc >= 1)
|
||||
{
|
||||
result = true;
|
||||
ffStrbufSetS(out, exp.we_wordv[0]);
|
||||
ffStrbufSetS(out, exp.we_wordv[exp.we_wordc > 1 ? ffTimeGetNow() % exp.we_wordc : 0]);
|
||||
}
|
||||
|
||||
wordfree(&exp);
|
||||
|
||||
#elif FF_HAVE_GLOB
|
||||
|
||||
glob_t gb;
|
||||
if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0)
|
||||
return false;
|
||||
|
||||
if (gb.gl_matchc >= 1)
|
||||
{
|
||||
result = true;
|
||||
ffStrbufSetS(out, gb.gl_pathv[gb.gl_matchc > 1 ? ffTimeGetNow() % gb.gl_matchc : 0]);
|
||||
}
|
||||
|
||||
globfree(&gb);
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
@@ -140,11 +180,11 @@ void restoreTerm(void)
|
||||
tcsetattr(ftty, TCSAFLUSH, &oldTerm);
|
||||
}
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...)
|
||||
{
|
||||
if (ftty < 0)
|
||||
{
|
||||
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
|
||||
ftty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||
if (ftty < 0)
|
||||
return "open(\"/dev/tty\", O_RDWR | O_NOCTTY | O_CLOEXEC) failed";
|
||||
|
||||
@@ -161,20 +201,54 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
ffWriteFDData(ftty, strlen(request), request);
|
||||
|
||||
//Give the terminal some time to respond
|
||||
#ifndef __APPLE__
|
||||
if(poll(&(struct pollfd) { .fd = ftty, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0)
|
||||
return "poll() timeout or failed";
|
||||
return "poll(/dev/tty) timeout or failed";
|
||||
#else
|
||||
{
|
||||
// On macOS, poll(/dev/tty) always returns immediately
|
||||
// See also https://nathancraddock.com/blog/macos-dev-tty-polling/
|
||||
fd_set rd;
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(ftty, &rd);
|
||||
if(select(ftty + 1, &rd, NULL, NULL, &(struct timeval) { .tv_sec = FF_IO_TERM_RESP_WAIT_MS / 1000, .tv_usec = (FF_IO_TERM_RESP_WAIT_MS % 1000) * 1000 }) <= 0)
|
||||
return "select(/dev/tty) timeout or failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
char buffer[512];
|
||||
ssize_t bytesRead = read(ftty, buffer, sizeof(buffer) - 1);
|
||||
|
||||
if(bytesRead <= 0)
|
||||
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
|
||||
|
||||
buffer[bytesRead] = '\0';
|
||||
char buffer[1024];
|
||||
size_t bytesRead = 0;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsscanf(buffer, format, args);
|
||||
|
||||
while (true)
|
||||
{
|
||||
ssize_t nRead = read(ftty, buffer + bytesRead, sizeof(buffer) - bytesRead - 1);
|
||||
|
||||
if (nRead <= 0)
|
||||
{
|
||||
va_end(args);
|
||||
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
|
||||
}
|
||||
|
||||
bytesRead += (size_t) nRead;
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
va_list cargs;
|
||||
va_copy(cargs, args);
|
||||
int ret = vsscanf(buffer, format, cargs);
|
||||
va_end(cargs);
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
va_end(args);
|
||||
return "vsscanf(buffer, format, args) failed";
|
||||
}
|
||||
if (ret >= nParams)
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return NULL;
|
||||
|
||||
+78
-13
@@ -3,6 +3,8 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
@@ -38,7 +40,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data)
|
||||
|
||||
static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length)
|
||||
{
|
||||
ffStrbufEnsureFixedLengthFree(buffer, length);
|
||||
ffStrbufEnsureFree(buffer, length);
|
||||
DWORD bytesRead = 0;
|
||||
while(
|
||||
length > 0 &&
|
||||
@@ -100,6 +102,49 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(handle, buffer);
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
UNICODE_STRING fileNameW;
|
||||
ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) {
|
||||
.Length = (USHORT) strlen(fileName),
|
||||
.Buffer = (PCHAR) fileName
|
||||
}, TRUE);
|
||||
if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hFile;
|
||||
IO_STATUS_BLOCK iosb = {};
|
||||
ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &fileNameW,
|
||||
}, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE));
|
||||
RtlFreeUnicodeString(&fileNameW);
|
||||
|
||||
if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
||||
bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
|
||||
if(fd == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
ssize_t ffReadFileDataRelative(HANDLE dfd, const char* fileName, size_t dataSize, void* data)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
|
||||
if(fd == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
|
||||
return ffReadFDData(fd, dataSize, data);
|
||||
}
|
||||
|
||||
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
|
||||
{
|
||||
DWORD length = ExpandEnvironmentStringsA(in, NULL, 0);
|
||||
@@ -205,7 +250,7 @@ void ffListFilesRecursively(const char* path, bool pretty)
|
||||
listFilesRecursively(folder.length, &folder, 0, NULL, pretty);
|
||||
}
|
||||
|
||||
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
const char* ffGetTerminalResponse(const char* request, int nParams, const char* format, ...)
|
||||
{
|
||||
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
FF_AUTO_CLOSE_FD HANDLE hConin = INVALID_HANDLE_VALUE;
|
||||
@@ -256,20 +301,40 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...)
|
||||
ReadConsoleInputW(hInput, &record, 1, &len);
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
DWORD bytes = 0;
|
||||
ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
char buffer[1024];
|
||||
uint32_t bytesRead = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
DWORD bytes = 0;
|
||||
if (!ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL) || bytes == 0)
|
||||
{
|
||||
va_end(args);
|
||||
return "ReadFile() failed";
|
||||
}
|
||||
|
||||
bytesRead += bytes;
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
va_list cargs;
|
||||
va_copy(cargs, args);
|
||||
int ret = vsscanf(buffer, format, args);
|
||||
va_end(cargs);
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
va_end(args);
|
||||
return "vsscanf(buffer, format, args) failed";
|
||||
}
|
||||
if (ret >= nParams)
|
||||
break;
|
||||
}
|
||||
|
||||
SetConsoleMode(hInput, inputMode);
|
||||
|
||||
if(bytes <= 0)
|
||||
return "ReadFile() failed";
|
||||
|
||||
buffer[bytes] = '\0';
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsscanf(buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
return NULL;
|
||||
|
||||
+27
-16
@@ -29,6 +29,17 @@ static void* libraryLoad(const char* path, int maxVersion)
|
||||
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
|
||||
FF_UNUSED(maxVersion)
|
||||
|
||||
if(result != NULL)
|
||||
return result;
|
||||
|
||||
uint32_t pathLen = ffStrbufLastIndexC(&instance.state.platform.exePath, '/');
|
||||
if (pathLen == instance.state.platform.exePath.length)
|
||||
return result;
|
||||
|
||||
char absPath[MAX_PATH + 1];
|
||||
strcpy(mempcpy(absPath, instance.state.platform.exePath.chars, pathLen + 1), path);
|
||||
return dlopen(absPath, FF_DLOPEN_FLAGS);
|
||||
|
||||
#else
|
||||
|
||||
if(result != NULL || maxVersion < 0)
|
||||
@@ -55,28 +66,28 @@ static void* libraryLoad(const char* path, int maxVersion)
|
||||
return result;
|
||||
}
|
||||
|
||||
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...)
|
||||
void* ffLibraryLoad(const char* path, int maxVersion, ...)
|
||||
{
|
||||
if(userProvidedName != NULL && userProvidedName->length > 0)
|
||||
return dlopen(userProvidedName->chars, FF_DLOPEN_FLAGS);
|
||||
void* result = libraryLoad(path, maxVersion);
|
||||
|
||||
va_list defaultNames;
|
||||
va_start(defaultNames, userProvidedName);
|
||||
|
||||
void* result = NULL;
|
||||
|
||||
while(result == NULL)
|
||||
if (!result)
|
||||
{
|
||||
const char* path = va_arg(defaultNames, const char*);
|
||||
if(path == NULL)
|
||||
break;
|
||||
va_list defaultNames;
|
||||
va_start(defaultNames, maxVersion);
|
||||
|
||||
int maxVersion = va_arg(defaultNames, int);
|
||||
result = libraryLoad(path, maxVersion);
|
||||
do
|
||||
{
|
||||
const char* pathRest = va_arg(defaultNames, const char*);
|
||||
if(pathRest == NULL)
|
||||
break;
|
||||
|
||||
int maxVersionRest = va_arg(defaultNames, int);
|
||||
result = libraryLoad(pathRest, maxVersionRest);
|
||||
} while (!result);
|
||||
|
||||
va_end(defaultNames);
|
||||
}
|
||||
|
||||
va_end(defaultNames);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+4
-24
@@ -33,8 +33,8 @@ static inline void ffLibraryUnload(void** handle)
|
||||
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||
__typeof__(&symbolName) ff ## symbolName;
|
||||
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
|
||||
void* __attribute__((__cleanup__(ffLibraryUnload))) libraryObjectName = ffLibraryLoad(userLibraryName, __VA_ARGS__, NULL);\
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
|
||||
void* __attribute__((__cleanup__(ffLibraryUnload))) libraryObjectName = ffLibraryLoad(__VA_ARGS__, NULL);\
|
||||
if(libraryObjectName == NULL) \
|
||||
return returnValue;
|
||||
|
||||
@@ -43,11 +43,6 @@ static inline void ffLibraryUnload(void** handle)
|
||||
if(symbolMapping == NULL) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \
|
||||
symbolMapping = dlsym(library, #symbolName); \
|
||||
if(symbolMapping == NULL && !(symbolMapping = (__typeof__(&symbolName)) dlsym(library, #alternateName))) \
|
||||
return returnValue;
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
@@ -57,22 +52,16 @@ static inline void ffLibraryUnload(void** handle)
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(library, symbolName, alternateName) \
|
||||
__typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(library, varName, symbolName, alternateName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, (varName).ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...);
|
||||
void* ffLibraryLoad(const char* path, int maxVersion, ...);
|
||||
|
||||
#else
|
||||
|
||||
@@ -81,15 +70,12 @@ void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...);
|
||||
#define FF_LIBRARY_SYMBOL(symbolName) \
|
||||
__typeof__(&symbolName) ff ## symbolName;
|
||||
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, userLibraryName, returnValue, ...) \
|
||||
#define FF_LIBRARY_LOAD(libraryObjectName, returnValue, ...) \
|
||||
FF_MAYBE_UNUSED void* libraryObjectName = NULL; // Placeholder
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||
symbolMapping = (__typeof__(&symbolName)) &symbolName
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, symbolMapping, symbolName, alternateName, returnValue) \
|
||||
symbolMapping = (__typeof__(&symbolName)) &symbolName
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName, returnValue) \
|
||||
FF_MAYBE_UNUSED __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
@@ -99,18 +85,12 @@ void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...);
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE(library, symbolName) \
|
||||
FF_MAYBE_UNUSED __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_MESSAGE2(library, symbolName, alternateName) \
|
||||
FF_MAYBE_UNUSED __typeof__(&symbolName) FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(library, varName, symbolName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName).ff ## symbolName, symbolName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE2(library, varName, symbolName, alternateName) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS2(library, (varName).ff ## symbolName, symbolName, alternateName, "dlsym " #symbolName " failed");
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_PTR(library, varName, symbolName, returnValue) \
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, (varName)->ff ## symbolName, symbolName, returnValue);
|
||||
|
||||
|
||||
+73
-69
@@ -5,64 +5,65 @@ static FFModuleBaseInfo* A[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* B[] = {
|
||||
(void*) &instance.config.modules.battery,
|
||||
(void*) &instance.config.modules.bios,
|
||||
(void*) &instance.config.modules.bluetooth,
|
||||
(void*) &instance.config.modules.bluetoothRadio,
|
||||
(void*) &instance.config.modules.board,
|
||||
(void*) &instance.config.modules.bootmgr,
|
||||
(void*) &instance.config.modules.break_,
|
||||
(void*) &instance.config.modules.brightness,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.battery,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.bios,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.bluetooth,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.bluetoothRadio,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.board,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.bootmgr,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.break_,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.brightness,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.btrfs,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* C[] = {
|
||||
(void*) &instance.config.modules.camera,
|
||||
(void*) &instance.config.modules.chassis,
|
||||
(void*) &instance.config.modules.command,
|
||||
(void*) &instance.config.modules.colors,
|
||||
(void*) &instance.config.modules.cpu,
|
||||
(void*) &instance.config.modules.cpuCache,
|
||||
(void*) &instance.config.modules.cpuUsage,
|
||||
(void*) &instance.config.modules.cursor,
|
||||
(void*) &instance.config.modules.custom,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.camera,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.chassis,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.command,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.colors,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.cpu,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.cpuCache,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.cpuUsage,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.cursor,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.custom,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* D[] = {
|
||||
(void*) &instance.config.modules.dateTime,
|
||||
(void*) &instance.config.modules.de,
|
||||
(void*) &instance.config.modules.display,
|
||||
(void*) &instance.config.modules.disk,
|
||||
(void*) &instance.config.modules.diskIo,
|
||||
(void*) &instance.config.modules.dns,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.dateTime,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.de,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.display,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.disk,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.diskIo,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.dns,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* E[] = {
|
||||
(void*) &instance.config.modules.editor,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.editor,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* F[] = {
|
||||
(void*) &instance.config.modules.font,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.font,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* G[] = {
|
||||
(void*) &instance.config.modules.gamepad,
|
||||
(void*) &instance.config.modules.gpu,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.gamepad,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.gpu,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* H[] = {
|
||||
(void*) &instance.config.modules.host,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.host,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* I[] = {
|
||||
(void*) &instance.config.modules.icons,
|
||||
(void*) &instance.config.modules.initSystem,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.icons,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.initSystem,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -71,45 +72,47 @@ static FFModuleBaseInfo* J[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* K[] = {
|
||||
(void*) &instance.config.modules.kernel,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.kernel,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.keyboard,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* L[] = {
|
||||
(void*) &instance.config.modules.lm,
|
||||
(void*) &instance.config.modules.loadavg,
|
||||
(void*) &instance.config.modules.locale,
|
||||
(void*) &instance.config.modules.localIP,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.lm,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.loadavg,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.locale,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.localIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* M[] = {
|
||||
(void*) &instance.config.modules.media,
|
||||
(void*) &instance.config.modules.memory,
|
||||
(void*) &instance.config.modules.monitor,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.media,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.memory,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.monitor,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.mouse,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* N[] = {
|
||||
(void*) &instance.config.modules.netIo,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.netIo,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* O[] = {
|
||||
(void*) &instance.config.modules.openCL,
|
||||
(void*) &instance.config.modules.openGL,
|
||||
(void*) &instance.config.modules.os,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.openCL,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.openGL,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.os,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* P[] = {
|
||||
(void*) &instance.config.modules.packages,
|
||||
(void*) &instance.config.modules.physicalDisk,
|
||||
(void*) &instance.config.modules.physicalMemory,
|
||||
(void*) &instance.config.modules.player,
|
||||
(void*) &instance.config.modules.powerAdapter,
|
||||
(void*) &instance.config.modules.processes,
|
||||
(void*) &instance.config.modules.publicIP,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.packages,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.physicalDisk,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.physicalMemory,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.player,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.powerAdapter,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.processes,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.publicIP,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -122,41 +125,42 @@ static FFModuleBaseInfo* R[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* S[] = {
|
||||
(void*) &instance.config.modules.separator,
|
||||
(void*) &instance.config.modules.shell,
|
||||
(void*) &instance.config.modules.sound,
|
||||
(void*) &instance.config.modules.swap,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.separator,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.shell,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.sound,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.swap,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* T[] = {
|
||||
(void*) &instance.config.modules.terminal,
|
||||
(void*) &instance.config.modules.terminalFont,
|
||||
(void*) &instance.config.modules.terminalSize,
|
||||
(void*) &instance.config.modules.terminalTheme,
|
||||
(void*) &instance.config.modules.title,
|
||||
(void*) &instance.config.modules.theme,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.terminal,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.terminalFont,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.terminalSize,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.terminalTheme,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.title,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.theme,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.tpm,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* U[] = {
|
||||
(void*) &instance.config.modules.uptime,
|
||||
(void*) &instance.config.modules.users,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.uptime,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.users,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* V[] = {
|
||||
(void*) &instance.config.modules.version,
|
||||
(void*) &instance.config.modules.vulkan,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.version,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.vulkan,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* W[] = {
|
||||
(void*) &instance.config.modules.wallpaper,
|
||||
(void*) &instance.config.modules.weather,
|
||||
(void*) &instance.config.modules.wm,
|
||||
(void*) &instance.config.modules.wifi,
|
||||
(void*) &instance.config.modules.wmTheme,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.wallpaper,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.weather,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.wm,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.wifi,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.wmTheme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -169,7 +173,7 @@ static FFModuleBaseInfo* Y[] = {
|
||||
};
|
||||
|
||||
static FFModuleBaseInfo* Z[] = {
|
||||
(void*) &instance.config.modules.zpool,
|
||||
(FFModuleBaseInfo*) &instance.config.modules.zpool,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
@@ -91,7 +91,11 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
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)
|
||||
if (sdl
|
||||
#ifndef __sun
|
||||
&& sdl->sdl_len
|
||||
#endif
|
||||
)
|
||||
{
|
||||
assert(sdl->sdl_nlen <= IF_NAMESIZE);
|
||||
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
|
||||
|
||||
@@ -13,11 +13,9 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
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,
|
||||
FF_UNUSED(fscanf(netRoute, "%*[^\n]\n"));
|
||||
|
||||
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;
|
||||
|
||||
@@ -132,5 +132,6 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
close(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
@@ -63,19 +63,21 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
{
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if(bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if((state->ipv6
|
||||
? bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = in6addr_any,
|
||||
}, sizeof(struct sockaddr_in6))
|
||||
: bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
.sin_port = 0,
|
||||
}, sizeof(struct sockaddr_in)) != 0)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
}, sizeof(struct sockaddr_in))) != 0)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
@@ -93,7 +95,6 @@ const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* ho
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
@@ -140,5 +141,6 @@ const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buf
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
closesocket(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
|
||||
+17
-24
@@ -6,6 +6,20 @@ struct yyjson_val;
|
||||
struct yyjson_mut_doc;
|
||||
struct yyjson_mut_val;
|
||||
|
||||
typedef struct FFModuleFormatArg
|
||||
{
|
||||
const char* desc;
|
||||
const char* name;
|
||||
} FFModuleFormatArg;
|
||||
|
||||
typedef struct FFModuleFormatArgList
|
||||
{
|
||||
FFModuleFormatArg* args;
|
||||
uint32_t count;
|
||||
} FFModuleFormatArgList;
|
||||
|
||||
#define FF_FORMAT_ARG_LIST(list) { .args = list, .count = sizeof(list) / sizeof(FFModuleFormatArg) }
|
||||
|
||||
// Must be the first field of FFModuleOptions
|
||||
typedef struct FFModuleBaseInfo
|
||||
{
|
||||
@@ -19,38 +33,17 @@ typedef struct FFModuleBaseInfo
|
||||
void (*parseJsonObject)(void* options, struct yyjson_val *module);
|
||||
void (*printModule)(void* options);
|
||||
void (*generateJsonResult)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module);
|
||||
void (*printHelpFormat)(void);
|
||||
void (*generateJsonConfig)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* obj);
|
||||
FFModuleFormatArgList formatArgs;
|
||||
} FFModuleBaseInfo;
|
||||
|
||||
static inline void ffOptionInitModuleBaseInfo(
|
||||
FFModuleBaseInfo* baseInfo,
|
||||
const char* name,
|
||||
const char* description,
|
||||
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* generateJsonResult, // void (*const generateJsonResult)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
void (*printHelpFormat)(void),
|
||||
void* generateJsonConfig // void (*const generateJsonConfig)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj)
|
||||
)
|
||||
{
|
||||
baseInfo->name = name;
|
||||
baseInfo->description = description;
|
||||
baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions;
|
||||
baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject;
|
||||
baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule;
|
||||
baseInfo->generateJsonResult = (__typeof__(baseInfo->generateJsonResult)) generateJsonResult;
|
||||
baseInfo->printHelpFormat = printHelpFormat;
|
||||
baseInfo->generateJsonConfig = (__typeof__(baseInfo->generateJsonConfig)) generateJsonConfig;
|
||||
}
|
||||
|
||||
typedef enum FFModuleKeyType
|
||||
typedef enum __attribute__((__packed__)) FFModuleKeyType
|
||||
{
|
||||
FF_MODULE_KEY_TYPE_NONE = 0,
|
||||
FF_MODULE_KEY_TYPE_STRING = 1 << 0,
|
||||
FF_MODULE_KEY_TYPE_ICON = 1 << 1,
|
||||
FF_MODULE_KEY_TYPE_BOTH = FF_MODULE_KEY_TYPE_STRING | FF_MODULE_KEY_TYPE_ICON,
|
||||
FF_MODULE_KEY_TYPE_FORCE_UNSIGNED = UINT8_MAX,
|
||||
} FFModuleKeyType;
|
||||
|
||||
typedef struct FFModuleArgs
|
||||
|
||||
+43
-1
@@ -72,7 +72,7 @@ static void parseSize(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
|
||||
}
|
||||
|
||||
if(counter == 0)
|
||||
ffStrbufAppendF(result, "%"PRIu64" %s", bytes, prefixes[0]);
|
||||
ffStrbufAppendF(result, "%" PRIu64 " %s", bytes, prefixes[0]);
|
||||
else
|
||||
ffStrbufAppendF(result, "%.*f %s", instance.config.display.sizeNdigits, size, prefixes[counter]);
|
||||
}
|
||||
@@ -190,6 +190,48 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
}
|
||||
}
|
||||
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result)
|
||||
{
|
||||
if(days == 0 && hours == 0 && minutes == 0)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u seconds", seconds);
|
||||
return;
|
||||
}
|
||||
|
||||
if(days > 0)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u day", days);
|
||||
|
||||
if(days > 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
|
||||
if(days >= 100)
|
||||
ffStrbufAppendS(result, "(!)");
|
||||
|
||||
if(hours > 0 || minutes > 0)
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
|
||||
if(hours > 0)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u hour", hours);
|
||||
|
||||
if(hours > 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
|
||||
if(minutes > 0)
|
||||
ffStrbufAppendS(result, ", ");
|
||||
}
|
||||
|
||||
if(minutes > 0)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u min", minutes);
|
||||
|
||||
if(minutes > 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@@ -27,3 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result);
|
||||
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result);
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result);
|
||||
|
||||
+72
-10
@@ -14,7 +14,46 @@ static void appendOutputColor(FFstrbuf* buffer, const FFModuleArgs* module)
|
||||
ffStrbufAppendF(buffer, "\e[%sm", instance.config.display.colorOutput.chars);
|
||||
}
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module)
|
||||
const char* ffPercentParseTypeJsonConfig(yyjson_val* jsonVal, FFPercentageTypeFlags* result)
|
||||
{
|
||||
if (yyjson_is_uint(jsonVal))
|
||||
{
|
||||
*result = (FFPercentageTypeFlags) yyjson_get_uint(jsonVal);
|
||||
return NULL;
|
||||
}
|
||||
if (yyjson_is_arr(jsonVal))
|
||||
{
|
||||
FFPercentageTypeFlags flags = 0;
|
||||
|
||||
yyjson_val* item;
|
||||
size_t idx, max;
|
||||
yyjson_arr_foreach(jsonVal, idx, max, item)
|
||||
{
|
||||
const char* flag = yyjson_get_str(item);
|
||||
if (!flag)
|
||||
return "Error: percent.type: invalid flag string";
|
||||
if (ffStrEqualsIgnCase(flag, "num"))
|
||||
flags |= FF_PERCENTAGE_TYPE_NUM_BIT;
|
||||
else if (ffStrEqualsIgnCase(flag, "bar"))
|
||||
flags |= FF_PERCENTAGE_TYPE_BAR_BIT;
|
||||
else if (ffStrEqualsIgnCase(flag, "hide-others"))
|
||||
flags |= FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT;
|
||||
else if (ffStrEqualsIgnCase(flag, "num-color"))
|
||||
flags |= FF_PERCENTAGE_TYPE_NUM_COLOR_BIT;
|
||||
else if (ffStrEqualsIgnCase(flag, "bar-monochrome"))
|
||||
flags |= FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT;
|
||||
else
|
||||
return "Error: percent.type: unknown flag string";
|
||||
}
|
||||
|
||||
*result = flags;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Error: usage: percent.type must be a number or an array of strings";
|
||||
}
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
@@ -41,15 +80,18 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* colorGreen = instance.config.display.percentColorGreen.chars;
|
||||
const char* colorYellow = instance.config.display.percentColorYellow.chars;
|
||||
const char* colorRed = instance.config.display.percentColorRed.chars;
|
||||
const char* colorGreen = options->percentColorGreen.chars;
|
||||
const char* colorYellow = options->percentColorYellow.chars;
|
||||
const char* colorRed = options->percentColorRed.chars;
|
||||
|
||||
FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type;
|
||||
bool monochrome = !!(percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT);
|
||||
|
||||
for (uint32_t i = 0; i < blocksPercent; ++i)
|
||||
{
|
||||
if(!options->pipe)
|
||||
{
|
||||
if (options->percentType & FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT)
|
||||
if (monochrome)
|
||||
{
|
||||
const char* color = NULL;
|
||||
if (green <= yellow)
|
||||
@@ -104,14 +146,15 @@ void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig con
|
||||
}
|
||||
}
|
||||
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module)
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module)
|
||||
{
|
||||
uint8_t green = config.green, yellow = config.yellow;
|
||||
assert(green <= 100 && yellow <= 100);
|
||||
|
||||
const FFOptionsDisplay* options = &instance.config.display;
|
||||
FFPercentageTypeFlags percentType = config.type == 0 ? options->percentType : config.type;
|
||||
|
||||
bool colored = !!(options->percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
bool colored = !!(percentType & FF_PERCENTAGE_TYPE_NUM_COLOR_BIT);
|
||||
|
||||
if (parentheses)
|
||||
ffStrbufAppendC(buffer, '(');
|
||||
@@ -156,7 +199,7 @@ void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig con
|
||||
ffStrbufAppendC(buffer, ')');
|
||||
}
|
||||
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config)
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config)
|
||||
{
|
||||
if (!ffStrStartsWithIgnCase(subkey, "percent-"))
|
||||
return false;
|
||||
@@ -187,10 +230,16 @@ bool ffPercentParseCommandOptions(const char* key, const char* subkey, const cha
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subkey, "type"))
|
||||
{
|
||||
config->type = (FFPercentageTypeFlags) ffOptionParseUInt32(key, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config)
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config)
|
||||
{
|
||||
if (!ffStrEqualsIgnCase(key, "percent"))
|
||||
return false;
|
||||
@@ -225,10 +274,21 @@ bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeCo
|
||||
config->yellow = (uint8_t) num;
|
||||
}
|
||||
|
||||
yyjson_val* typeVal = yyjson_obj_get(value, "type");
|
||||
if (typeVal)
|
||||
{
|
||||
const char* error = ffPercentParseTypeJsonConfig(typeVal, &config->type);
|
||||
if (error)
|
||||
{
|
||||
fputs(error, stderr);
|
||||
exit(480);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config)
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config)
|
||||
{
|
||||
if (config.green == defaultConfig.green && config.yellow == defaultConfig.yellow)
|
||||
return;
|
||||
@@ -238,4 +298,6 @@ void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FF
|
||||
yyjson_mut_obj_add_uint(doc, percent, "green", config.green);
|
||||
if (config.yellow != defaultConfig.yellow)
|
||||
yyjson_mut_obj_add_uint(doc, percent, "yellow", config.yellow);
|
||||
if (config.type != defaultConfig.type)
|
||||
yyjson_mut_obj_add_uint(doc, percent, "type", config.type);
|
||||
}
|
||||
|
||||
+18
-7
@@ -4,14 +4,24 @@
|
||||
#include "common/parsing.h"
|
||||
#include "common/option.h"
|
||||
|
||||
enum FFPercentageTypeFlags
|
||||
typedef enum __attribute__((__packed__)) FFPercentageTypeFlags
|
||||
{
|
||||
FF_PERCENTAGE_TYPE_NONE = 0,
|
||||
FF_PERCENTAGE_TYPE_NUM_BIT = 1 << 0,
|
||||
FF_PERCENTAGE_TYPE_BAR_BIT = 1 << 1,
|
||||
FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT = 1 << 2,
|
||||
FF_PERCENTAGE_TYPE_NUM_COLOR_BIT = 1 << 3,
|
||||
FF_PERCENTAGE_TYPE_BAR_MONOCHROME_BIT = FF_PERCENTAGE_TYPE_NUM_COLOR_BIT,
|
||||
};
|
||||
FF_PERCENTAGE_TYPE_FORCE_UNSIGNED_ = UINT8_MAX,
|
||||
} FFPercentageTypeFlags;
|
||||
static_assert(sizeof(FFPercentageTypeFlags) == 1, "");
|
||||
|
||||
typedef struct FFPercentageModuleConfig
|
||||
{
|
||||
uint8_t green;
|
||||
uint8_t yellow;
|
||||
FFPercentageTypeFlags type;
|
||||
} FFPercentageModuleConfig;
|
||||
|
||||
// if (green <= yellow)
|
||||
// [0, green]: print green
|
||||
@@ -23,12 +33,13 @@ enum FFPercentageTypeFlags
|
||||
// [yellow, green): print yellow
|
||||
// [0, yellow): print red
|
||||
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFColorRangeConfig config, const FFModuleArgs* module);
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFColorRangeConfig config, bool parentheses, const FFModuleArgs* module);
|
||||
void ffPercentAppendBar(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, const FFModuleArgs* module);
|
||||
void ffPercentAppendNum(FFstrbuf* buffer, double percent, FFPercentageModuleConfig config, bool parentheses, const FFModuleArgs* module);
|
||||
|
||||
typedef struct yyjson_val yyjson_val;
|
||||
typedef struct yyjson_mut_doc yyjson_mut_doc;
|
||||
typedef struct yyjson_mut_val yyjson_mut_val;
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFColorRangeConfig* config);
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFColorRangeConfig* config);
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFColorRangeConfig defaultConfig, FFColorRangeConfig config);
|
||||
bool ffPercentParseCommandOptions(const char* key, const char* subkey, const char* value, FFPercentageModuleConfig* config);
|
||||
bool ffPercentParseJsonObject(const char* key, yyjson_val* value, FFPercentageModuleConfig* config);
|
||||
void ffPercentGenerateJsonConfig(yyjson_mut_doc* doc, yyjson_mut_val* module, FFPercentageModuleConfig defaultConfig, FFPercentageModuleConfig config);
|
||||
const char* ffPercentParseTypeJsonConfig(yyjson_val* value, FFPercentageTypeFlags* result);
|
||||
|
||||
+3
-18
@@ -50,9 +50,9 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, 2, ((FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_UINT8, &moduleIndex, "index"},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &moduleArgs->keyIcon, "icon"},
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &moduleArgs->key, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(moduleIndex, "index"),
|
||||
FF_FORMAT_ARG(moduleArgs->keyIcon, "icon"),
|
||||
}));
|
||||
ffStrbufWriteTo(&key, stdout);
|
||||
}
|
||||
@@ -148,18 +148,3 @@ 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);
|
||||
}
|
||||
|
||||
+4
-11
@@ -3,26 +3,19 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/format.h"
|
||||
|
||||
typedef enum FFPrintType {
|
||||
typedef enum __attribute__((__packed__)) FFPrintType {
|
||||
FF_PRINT_TYPE_DEFAULT = 0,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY = 1 << 0, // key has been formatted outside
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY_COLOR = 1 << 1,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_KEY_WIDTH = 1 << 2,
|
||||
FF_PRINT_TYPE_NO_CUSTOM_OUTPUT_FORMAT = 1 << 3, // reserved
|
||||
FF_PRINT_TYPE_FORCE_UNSIGNED = UINT8_MAX,
|
||||
} FFPrintType;
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType);
|
||||
void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments);
|
||||
#define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, numArgs, arguments) do {\
|
||||
static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (numArgs), (arguments));\
|
||||
} while (0)
|
||||
#define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, arguments) \
|
||||
ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (sizeof(arguments) / sizeof(*arguments)), (arguments));
|
||||
FF_C_PRINTF(5, 6) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...);
|
||||
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[]);
|
||||
#define FF_PRINT_MODULE_FORMAT_HELP_CHECKED(moduleName, def, numArgs, args) do {\
|
||||
static_assert(sizeof(args) / sizeof(*(args)) == (numArgs), "Invalid number of format arguments");\
|
||||
ffPrintModuleFormatHelp((moduleName), (def), (numArgs), (args));\
|
||||
} while (0)
|
||||
|
||||
+121
-23
@@ -1,7 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/time.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
@@ -22,6 +21,13 @@
|
||||
#include <libproc.h>
|
||||
#elif defined(__sun)
|
||||
#include <procfs.h>
|
||||
#elif defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <kvm.h>
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
@@ -83,6 +89,16 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
@@ -97,7 +113,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
else if (nRead == 0)
|
||||
{
|
||||
int stat_loc = 0;
|
||||
if (waitpid(childPid, &stat_loc, 0) == childPid)
|
||||
if (childPid > 0 && waitpid(childPid, &stat_loc, 0) == childPid)
|
||||
{
|
||||
if (!WIFEXITED(stat_loc))
|
||||
return "child process exited abnormally";
|
||||
@@ -106,10 +122,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
// We only handle 127 as an error. See `getTerminalVersionUrxvt` in `terminalshell.c`
|
||||
return NULL;
|
||||
}
|
||||
return "waitpid() failed";
|
||||
return NULL;
|
||||
}
|
||||
else if (nRead < 0)
|
||||
break;
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
return NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
||||
@@ -135,12 +156,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (exePath)
|
||||
{
|
||||
snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid);
|
||||
ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX);
|
||||
ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1);
|
||||
char buf[PATH_MAX];
|
||||
ssize_t length = readlink(filePath, buf, PATH_MAX - 1);
|
||||
if (length > 0) // doesn't contain trailing NUL
|
||||
{
|
||||
exePath->chars[length] = '\0';
|
||||
exePath->length = (uint32_t) length;
|
||||
buf[length] = '\0';
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,14 +170,12 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
|
||||
size_t len = 0;
|
||||
int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid };
|
||||
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), NULL, &len, NULL, 0) == 0)
|
||||
if (sysctl(mibs, ARRAY_SIZE(mibs), NULL, &len, NULL, 0) == 0)
|
||||
{// try get arg0
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
//don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version.
|
||||
len++;
|
||||
#endif
|
||||
FF_AUTO_FREE char* const procArgs2 = malloc(len);
|
||||
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), procArgs2, &len, NULL, 0) == 0)
|
||||
if (sysctl(mibs, ARRAY_SIZE(mibs), procArgs2, &len, NULL, 0) == 0)
|
||||
{
|
||||
// https://gist.github.com/nonowarn/770696#file-getargv-c-L46
|
||||
uint32_t argc = *(uint32_t*) procArgs2;
|
||||
@@ -187,17 +207,18 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufEnsureFixedLengthFree(exe, PATH_MAX);
|
||||
int length = proc_pidpath(pid, exe->chars, exe->allocated);
|
||||
char buf[PROC_PIDPATHINFO_MAXSIZE];
|
||||
int length = proc_pidpath(pid, buf, ARRAY_SIZE(buf));
|
||||
if (length > 0)
|
||||
{
|
||||
exe->length = (uint32_t) length;
|
||||
ffStrbufEnsureFixedLengthFree(exe, (uint32_t) length);
|
||||
ffStrbufAppendNS(exe, (uint32_t) length, buf);
|
||||
if (exePath)
|
||||
ffStrbufSet(exePath, exe);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
|
||||
size_t size = ARG_MAX;
|
||||
FF_AUTO_FREE char* args = malloc(size);
|
||||
@@ -205,7 +226,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
static_assert(ARG_MAX > PATH_MAX, "");
|
||||
|
||||
if(exePath && sysctl(
|
||||
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid}, 4,
|
||||
(int[]){CTL_KERN,
|
||||
#if __FreeBSD__
|
||||
KERN_PROC, KERN_PROC_PATHNAME, pid
|
||||
#else
|
||||
KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME
|
||||
#endif
|
||||
}, 4,
|
||||
args, &size,
|
||||
NULL, 0
|
||||
) == 0)
|
||||
@@ -213,7 +240,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
|
||||
size = ARG_MAX;
|
||||
if(sysctl(
|
||||
(int[]){CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid}, 4,
|
||||
(int[]){CTL_KERN,
|
||||
#if __FreeBSD__
|
||||
KERN_PROC, KERN_PROC_ARGS, pid
|
||||
#else
|
||||
KERN_PROC_ARGS, pid, KERN_PROC_ARGV,
|
||||
#endif
|
||||
}, 4,
|
||||
args, &size,
|
||||
NULL, 0
|
||||
) == 0)
|
||||
@@ -238,7 +271,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
|
||||
#elif defined(__sun)
|
||||
|
||||
char filePath[PATH_MAX];
|
||||
char filePath[128];
|
||||
snprintf(filePath, sizeof(filePath), "/proc/%d/psinfo", (int) pid);
|
||||
psinfo_t proc;
|
||||
if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc))
|
||||
@@ -250,15 +283,28 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (exePath)
|
||||
{
|
||||
snprintf(filePath, sizeof(filePath), "/proc/%d/path/a.out", (int) pid);
|
||||
ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX);
|
||||
ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1);
|
||||
char buf[PATH_MAX];
|
||||
ssize_t length = readlink(filePath, buf, PATH_MAX - 1);
|
||||
if (length > 0) // doesn't contain trailing NUL
|
||||
{
|
||||
exePath->chars[length] = '\0';
|
||||
exePath->length = (uint32_t) length;
|
||||
buf[length] = '\0';
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
int count = 0;
|
||||
const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count);
|
||||
if (proc)
|
||||
{
|
||||
char** argv = kvm_getargv(kd, proc, 0);
|
||||
if (argv) ffStrbufSetS(exe, argv[0]);
|
||||
}
|
||||
kvm_close(kd);
|
||||
|
||||
#endif
|
||||
|
||||
if(exe->length == 0)
|
||||
@@ -334,6 +380,13 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#define ki_comm kp_comm
|
||||
#define ki_ppid kp_ppid
|
||||
#define ki_tdev kp_tdev
|
||||
#define ki_flag kp_flags
|
||||
#endif
|
||||
|
||||
struct kinfo_proc proc;
|
||||
size_t size = sizeof(proc);
|
||||
if(sysctl(
|
||||
@@ -360,6 +413,34 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
|
||||
*tty = -1;
|
||||
}
|
||||
|
||||
#elif defined(__NetBSD__)
|
||||
|
||||
struct kinfo_proc2 proc;
|
||||
size_t size = sizeof(proc);
|
||||
if(sysctl(
|
||||
(int[]){CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid, sizeof(proc), 1}, 6,
|
||||
&proc, &size,
|
||||
NULL, 0
|
||||
) != 0)
|
||||
return "sysctl(KERN_PROC_PID) failed";
|
||||
|
||||
ffStrbufSetS(name, proc.p_comm);
|
||||
if (ppid)
|
||||
*ppid = (pid_t)proc.p_ppid;
|
||||
if (tty)
|
||||
{
|
||||
if (proc.p_flag & P_CONTROLT)
|
||||
{
|
||||
const char* ttyName = devname(proc.p_tdev, S_IFCHR);
|
||||
if (ffStrStartsWith(ttyName, "pts/"))
|
||||
*tty = (int32_t) strtol(ttyName + strlen("pts/"), NULL, 10);
|
||||
else
|
||||
*tty = -1;
|
||||
}
|
||||
else
|
||||
*tty = -1;
|
||||
}
|
||||
|
||||
#elif defined(__sun)
|
||||
char path[128];
|
||||
snprintf(path, sizeof(path), "/proc/%d/psinfo", (int) pid);
|
||||
@@ -373,6 +454,23 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
|
||||
if (tty)
|
||||
*tty = (int) proc.pr_ttydev;
|
||||
|
||||
#elif defined(__OpenBSD__)
|
||||
|
||||
kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
|
||||
int count = 0;
|
||||
const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count);
|
||||
if (proc)
|
||||
{
|
||||
ffStrbufSetS(name, proc->p_comm);
|
||||
if (ppid)
|
||||
*ppid = proc->p_ppid;
|
||||
if (tty)
|
||||
*tty = (int) proc->p_tdev;
|
||||
}
|
||||
kvm_close(kd);
|
||||
if (!proc)
|
||||
return "kvm_getprocs() failed";
|
||||
|
||||
#else
|
||||
|
||||
return "Unsupported platform";
|
||||
|
||||
@@ -8,12 +8,52 @@
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
static void argvToCmdline(char* const argv[], FFstrbuf* result)
|
||||
{
|
||||
// From https://gist.github.com/jin-x/cdd641d98887524b091fb1f82a68717d
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY temp = ffStrbufCreate();
|
||||
for (int i = 0; argv[i] != NULL; i++)
|
||||
{
|
||||
ffStrbufSetS(&temp, argv[i]);
|
||||
// Add slash (\) before double quotes (") and duplicate slashes before it
|
||||
for (
|
||||
uint32_t pos = ffStrbufFirstIndexC(&temp, '"'), cnt;
|
||||
pos != temp.length;
|
||||
pos = ffStrbufNextIndexC(&temp, pos + cnt * 2, '"')
|
||||
) {
|
||||
cnt = 1;
|
||||
while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; }
|
||||
ffStrbufInsertNC(&temp, pos, cnt, '\\');
|
||||
}
|
||||
|
||||
// Add quotes around string if whitespace chars are present (with slash duplicating at the end of string)
|
||||
if (ffStrbufFirstIndexS(&temp, " \t") != temp.length)
|
||||
{
|
||||
uint32_t pos = temp.length;
|
||||
uint32_t cnt = 0;
|
||||
while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; }
|
||||
if (cnt > 0) ffStrbufAppendNC(&temp, cnt, '\\');
|
||||
ffStrbufPrependC(&temp, '"');
|
||||
ffStrbufAppendC(&temp, '"');
|
||||
}
|
||||
|
||||
// Add space delimiter
|
||||
if (i > 0) ffStrbufAppendC(result, ' ');
|
||||
ffStrbufAppend(result, &temp);
|
||||
ffStrbufClear(&temp);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int timeout = instance.config.general.processingTimeout;
|
||||
|
||||
wchar_t pipeName[32];
|
||||
swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u", GetCurrentProcessId());
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW(
|
||||
L"\\\\.\\pipe\\LOCAL\\",
|
||||
pipeName,
|
||||
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | (timeout < 0 ? 0 : FILE_FLAG_OVERLAPPED),
|
||||
0,
|
||||
1,
|
||||
@@ -23,10 +63,10 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
NULL
|
||||
);
|
||||
if (hChildPipeRead == INVALID_HANDLE_VALUE)
|
||||
return "CreateNamedPipeW(L\"\\\\.\\pipe\\LOCAL\\\") failed";
|
||||
return "CreateNamedPipeW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
HANDLE hChildPipeWrite = CreateFileW(
|
||||
L"\\\\.\\pipe\\LOCAL\\",
|
||||
pipeName,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
&(SECURITY_ATTRIBUTES){
|
||||
@@ -39,7 +79,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
NULL
|
||||
);
|
||||
if (hChildPipeWrite == INVALID_HANDLE_VALUE)
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\LOCAL\\\") failed";
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {0};
|
||||
|
||||
@@ -55,12 +95,8 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
else
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreateF("\"%s\"", argv[0]);
|
||||
for(char* const* parg = &argv[1]; *parg; ++parg)
|
||||
{
|
||||
ffStrbufAppendC(&cmdline, ' ');
|
||||
ffStrbufAppendS(&cmdline, *parg);
|
||||
}
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
|
||||
success = CreateProcessA(
|
||||
NULL, // application name
|
||||
@@ -133,6 +169,9 @@ bool ffProcessGetInfoWindows(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFst
|
||||
? GetCurrentProcess()
|
||||
: OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
|
||||
if (hProcess == NULL)
|
||||
return false;
|
||||
|
||||
if (gui)
|
||||
*gui = GetGuiResources(hProcess, GR_GDIOBJECTS) > 0;
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer
|
||||
bool valueStorage[32];
|
||||
bool* unsetValues = valueStorage;
|
||||
|
||||
if (numQueries > sizeof(valueStorage) / sizeof(valueStorage[0]))
|
||||
if (numQueries > ARRAY_SIZE(valueStorage))
|
||||
unsetValues = malloc(sizeof(bool) * numQueries);
|
||||
|
||||
bool allSet = true;
|
||||
|
||||
@@ -60,7 +60,7 @@ static const GSettingsData* getGSettingsData(void)
|
||||
if (!data.inited)
|
||||
{
|
||||
data.inited = true;
|
||||
FF_LIBRARY_LOAD(libgsettings, &instance.config.library.libGIO, NULL, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD(libgsettings, NULL, "libgio-2.0" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libgsettings, data, g_settings_schema_source_lookup, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libgsettings, data, g_settings_schema_has_key, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libgsettings, data, g_settings_new_full, NULL)
|
||||
@@ -141,7 +141,7 @@ static const DConfData* getDConfData(void)
|
||||
{
|
||||
data.inited = true;
|
||||
|
||||
FF_LIBRARY_LOAD(libdconf, &instance.config.library.libDConf, NULL, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
FF_LIBRARY_LOAD(libdconf, NULL, "libdconf" FF_LIBRARY_EXTENSION, 2);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libdconf, data, dconf_client_read_full, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libdconf, data, dconf_client_new, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libdconf, data.variantGetters, g_variant_dup_string, NULL)
|
||||
@@ -218,7 +218,7 @@ static const XFConfData* getXFConfData(void)
|
||||
if (!data.inited)
|
||||
{
|
||||
data.inited = true;
|
||||
FF_LIBRARY_LOAD(libxfconf, &instance.config.library.libXFConf, NULL, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
FF_LIBRARY_LOAD(libxfconf, NULL, "libxfconf-0" FF_LIBRARY_EXTENSION, 4);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_get, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libxfconf, data, xfconf_channel_has_property, NULL)
|
||||
@@ -292,7 +292,7 @@ static const SQLiteData* getSQLiteData(void)
|
||||
if (!data.inited)
|
||||
{
|
||||
data.inited = true;
|
||||
FF_LIBRARY_LOAD(libsqlite, &instance.config.library.libSQLite3, NULL, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD(libsqlite, NULL, "libsqlite3" FF_LIBRARY_EXTENSION, 1);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libsqlite, data, sqlite3_open_v2, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libsqlite, data, sqlite3_prepare_v2, NULL)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR(libsqlite, data, sqlite3_step, NULL)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef enum FFvarianttype
|
||||
typedef enum __attribute__((__packed__)) FFvarianttype
|
||||
{
|
||||
FF_VARIANT_TYPE_STRING,
|
||||
FF_VARIANT_TYPE_BOOL,
|
||||
|
||||
@@ -2,6 +2,41 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result)
|
||||
{
|
||||
size_t neededLength;
|
||||
if (sysctl((int[]) {mib1, mib2}, 2, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator
|
||||
return "sysctlbyname() failed";
|
||||
|
||||
ffStrbufEnsureFree(result, (uint32_t) neededLength - 1);
|
||||
|
||||
if (sysctl((int[]) {mib1, mib2}, 2, result->chars + result->length, &neededLength, NULL, 0) == 0)
|
||||
result->length += (uint32_t) neededLength - 1;
|
||||
|
||||
result->chars[result->length] = '\0';
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ffSysctlGetInt(int mib1, int mib2, int defaultValue)
|
||||
{
|
||||
int result;
|
||||
size_t neededLength = sizeof(result);
|
||||
if (sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0)
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue)
|
||||
{
|
||||
int64_t result;
|
||||
size_t neededLength = sizeof(result);
|
||||
if(sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0)
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
const char* ffSysctlGetString(const char* propName, FFstrbuf* result)
|
||||
{
|
||||
size_t neededLength;
|
||||
@@ -35,6 +70,7 @@ int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue)
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
#endif // OpenBSD
|
||||
|
||||
void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result);
|
||||
FF_C_NODISCARD int ffSysctlGetInt(int mib1, int mib2, int defaultValue);
|
||||
FF_C_NODISCARD int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue);
|
||||
#else
|
||||
const char* ffSysctlGetString(const char* propName, FFstrbuf* result);
|
||||
FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue);
|
||||
FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue);
|
||||
#endif
|
||||
FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength);
|
||||
|
||||
+12
-4
@@ -36,11 +36,19 @@
|
||||
#if FF_HAVE_PTHREAD_NP
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
typedef pthread_mutex_t FFThreadMutex;
|
||||
typedef pthread_t FFThreadType;
|
||||
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
|
||||
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
|
||||
#if __APPLE__
|
||||
#include <os/lock.h>
|
||||
#define FF_THREAD_MUTEX_INITIALIZER OS_UNFAIR_LOCK_INIT
|
||||
typedef os_unfair_lock FFThreadMutex;
|
||||
static inline void ffThreadMutexLock(os_unfair_lock* mutex) { os_unfair_lock_lock(mutex); }
|
||||
static inline void ffThreadMutexUnlock(os_unfair_lock* mutex) { os_unfair_lock_unlock(mutex); }
|
||||
#else
|
||||
#define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
typedef pthread_mutex_t FFThreadMutex;
|
||||
static inline void ffThreadMutexLock(FFThreadMutex* mutex) { pthread_mutex_lock(mutex); }
|
||||
static inline void ffThreadMutexUnlock(FFThreadMutex* mutex) { pthread_mutex_unlock(mutex); }
|
||||
#endif
|
||||
static inline FFThreadType ffThreadCreate(void* (* func)(void*), void* data) {
|
||||
FFThreadType newThread = 0;
|
||||
pthread_create(&newThread, NULL, func, data);
|
||||
|
||||
+97
-180
@@ -128,7 +128,7 @@
|
||||
"desc": "Set the timeout (ms) when waiting for child processes",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 1000
|
||||
"default": 5000
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -186,7 +186,8 @@
|
||||
"data-raw": "Text data, printed as is",
|
||||
"sixel": "Image file, printed as sixel codes",
|
||||
"kitty": "Image file, printed as kitty graphics protocol",
|
||||
"kitty_direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
|
||||
"kitty-direct": "Image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)",
|
||||
"kitty-icat": "Image file, use `kitten icat` to display the image. Requires binary `kitten` to be installed",
|
||||
"iterm": "Image file, printed as iterm graphics protocol",
|
||||
"chafa": "Image file, printed as ascii art using libchafa",
|
||||
"raw": "Image file, printed as raw binary string",
|
||||
@@ -351,6 +352,14 @@
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "kitty-icat",
|
||||
"desc": "Short for --logo-type kitty-icat --logo <path>",
|
||||
"remark": "See \"--help logo-type\" for more info",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "iterm",
|
||||
"desc": "Short for --logo-type iterm --logo <path>",
|
||||
@@ -766,184 +775,6 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"Library path": [
|
||||
{
|
||||
"long": "lib-vulkan",
|
||||
"desc": "Vulkan module & fallback for GPU output",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-wayland",
|
||||
"desc": "Better display performance and output in wayland sessions",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-xcb-randr",
|
||||
"desc": "X11 sessions for better display detection and faster WM detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-xcb",
|
||||
"desc": "X11 sessions for better display detection and faster WM detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-xrandr",
|
||||
"desc": "X11 sessions for better display detection and faster WM detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-x11",
|
||||
"desc": "X11 sessions for better display detection and faster WM detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-drm",
|
||||
"desc": "Used for fast resolution and refresh rate detection",
|
||||
"remark": "Linux only",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-gio",
|
||||
"desc": "Needed for values that are only stored GSettings",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-dconf",
|
||||
"desc": "Needed for values that are only stored in DConf + Fallback for GSettings",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-dbus",
|
||||
"desc": "Bluetooth, Player & Media detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-xfconf",
|
||||
"desc": "Needed for XFWM theme and XFCE Terminal font",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-sqlite3",
|
||||
"desc": "Needed for pkg & rpm package count",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-rpm",
|
||||
"desc": "Slower fallback for rpm package count",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-imagemagick",
|
||||
"desc": "Images in terminal using sixel or kitty graphics protocol",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-z",
|
||||
"desc": "Libz. Faster image output when using kitty graphics protocol",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-chafa",
|
||||
"desc": "Image output as ascii art",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-egl",
|
||||
"desc": "Needed by the OpenGL module for gl context creation",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-glx",
|
||||
"desc": "Needed by the OpenGL module for gl context creation",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-osmesa",
|
||||
"desc": "Needed by the OpenGL module for gl context creation",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-opencl",
|
||||
"desc": "OpenCL module",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-pulse",
|
||||
"desc": "Pulseaudio. Used for Sound detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-nm",
|
||||
"desc": "NetworkManager. Used for Wifi detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-freetype",
|
||||
"desc": "Used for Termux font detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-ddcutil",
|
||||
"desc": "Used for brightness detection of external displays",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "lib-elf",
|
||||
"desc": "Used for st terminal font detection and systemd version detection",
|
||||
"arg": {
|
||||
"type": "path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Module specific": [
|
||||
{
|
||||
"long": "title-fqdn",
|
||||
@@ -1094,6 +925,14 @@
|
||||
"type": "str"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "diskio-wait-time",
|
||||
"desc": "Set the wait time (in ms) when detecting disk usage",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 1000
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "physicaldisk-name-prefix",
|
||||
"desc": "Show disks with given name prefix only",
|
||||
@@ -1178,6 +1017,14 @@
|
||||
"default": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "brightness-compact",
|
||||
"desc": "Set if multiple results should be printed in one line",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "sound-type",
|
||||
"desc": "Set what type of sound devices should be printed",
|
||||
@@ -1240,6 +1087,14 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "cpuusage-wait-time",
|
||||
"desc": "Set the wait time (in ms) when detecting CPU usage",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 200
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "de-slow-version-detection",
|
||||
"desc": "Set if DE version should be detected with slow operations",
|
||||
@@ -1366,6 +1221,24 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-show-mtu",
|
||||
"desc": "Show net interface's MTU (Maximum Transmission Unit) size in bytes",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-show-speed",
|
||||
"desc": "Show net interface's link speed with human-readable format (or an 1Mb units integer in JSON format)",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-show-prefix-len",
|
||||
"desc": "Show network prefix length (/N) in local ip module",
|
||||
@@ -1401,6 +1274,15 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-show-flags",
|
||||
"desc": "Show net interface flags in local ip module",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "localip-compact",
|
||||
"desc": "Show all IPs in one line",
|
||||
@@ -1448,6 +1330,14 @@
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "netio-wait-time",
|
||||
"desc": "Set the wait time (in ms) when detecting network usage",
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 1000
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "publicip-timeout",
|
||||
"desc": "Time in milliseconds to wait for the public ip server to respond",
|
||||
@@ -1554,6 +1444,15 @@
|
||||
"default": "\"cmd\" for Windows; \"/bin/sh\" for *nix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "command-param",
|
||||
"desc": "Set the parameter used when starting the shell",
|
||||
"remark": "If set to empty string, it will be ignored",
|
||||
"arg": {
|
||||
"type": "str",
|
||||
"default": "\"/c\" for Windows; \"-c\" for *nix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "command-key",
|
||||
"desc": "Set the module key to display",
|
||||
@@ -1712,6 +1611,24 @@
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-percent-type",
|
||||
"desc": "Set the percentage output type",
|
||||
"remark": [
|
||||
"0 for use global `--percent-type` value",
|
||||
"1 for percentage number",
|
||||
"2 for multi-color bar",
|
||||
"3 for both",
|
||||
"6 for bar only",
|
||||
"9 for colored number",
|
||||
"10 for monochrome bar"
|
||||
],
|
||||
"arg": {
|
||||
"type": "num",
|
||||
"default": 0
|
||||
},
|
||||
"pseudo": true
|
||||
},
|
||||
{
|
||||
"long": "<module>-temp-green",
|
||||
"desc": [
|
||||
|
||||
@@ -17,6 +17,10 @@ In 2.23.0 or newer, `<` or `>` can be specified instead of `:` to set a left or
|
||||
For example: "--title-format '{user-name<20}'" will generate `<user-name> `;
|
||||
"--title-format '{user-name>20}'" will generate ` <user-name>`
|
||||
|
||||
In 2.24.0 or newer, `{~startIndex,endIndex}` can be specified to slice a string. Negative index counts back from the end of the string.
|
||||
If an index is omitted, 0 is used. For example, both `{~,0}` `{~0,}` and `{~,}` are same as `{~0,0}` and will always generate a empty string.
|
||||
If `,endIndex` is omitted or greater than the length of the string, the length of string is used.
|
||||
|
||||
If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index.
|
||||
This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})".
|
||||
Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again.
|
||||
|
||||
@@ -15,6 +15,7 @@ typedef struct FFBatteryResult
|
||||
double capacity;
|
||||
double temperature;
|
||||
uint32_t cycleCount;
|
||||
int32_t timeRemaining;
|
||||
} FFBatteryResult;
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
|
||||
#include "util/stringUtils.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
|
||||
@@ -36,6 +36,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
battery->timeRemaining = -1;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
@@ -44,7 +45,27 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results)
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage"));
|
||||
ffStrbufAppendS(&battery->status, yyjson_get_str(yyjson_obj_get(root, "status")));
|
||||
const char* acStatus = yyjson_get_str(yyjson_obj_get(root, "plugged"));
|
||||
if (acStatus)
|
||||
{
|
||||
if (ffStrEquals(acStatus, "PLUGGED_AC"))
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
else if (ffStrEquals(acStatus, "PLUGGED_USB"))
|
||||
ffStrbufAppendS(&battery->status, "USB Connected, ");
|
||||
else if (ffStrEquals(acStatus, "PLUGGED_WIRELESS"))
|
||||
ffStrbufAppendS(&battery->status, "Wireless Connected, ");
|
||||
}
|
||||
const char* status = yyjson_get_str(yyjson_obj_get(root, "status"));
|
||||
if (status)
|
||||
{
|
||||
if (ffStrEquals(status, "CHARGING"))
|
||||
ffStrbufAppendS(&battery->status, "Charging");
|
||||
else if (ffStrEquals(status, "DISCHARGING"))
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
}
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
if(options->temp)
|
||||
battery->temperature = yyjson_get_num(yyjson_obj_get(root, "temperature"));
|
||||
|
||||
@@ -74,6 +95,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results)
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
battery->timeRemaining = -1;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "detection/temps/temps_apple.h"
|
||||
#include "util/apple/smc_temps.h"
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/pwr_mgt/IOPM.h>
|
||||
@@ -57,13 +57,24 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
ffCfDictGetInt(properties, CFSTR(kIOPMPSCycleCountKey), &cycleCount);
|
||||
battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount;
|
||||
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "AC connected, ");
|
||||
else
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) && boolValue)
|
||||
battery->timeRemaining = -1;
|
||||
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) == NULL)
|
||||
{
|
||||
if (boolValue)
|
||||
ffStrbufAppendS(&battery->status, "AC connected, ");
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
ffCfDictGetInt(properties, CFSTR("AvgTimeToEmpty"), &battery->timeRemaining); // in minutes
|
||||
if (battery->timeRemaining < 0 || battery->timeRemaining >= 0xFFFF)
|
||||
battery->timeRemaining = -1;
|
||||
else
|
||||
battery->timeRemaining *= 60;
|
||||
}
|
||||
}
|
||||
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) == NULL && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) && boolValue)
|
||||
if (ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) == NULL && boolValue)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
@@ -41,7 +41,9 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
battery->timeRemaining = -1;
|
||||
if (battio.battinfo.min > 0)
|
||||
battery->timeRemaining = battio.battinfo.min * 60;
|
||||
battery->capacity = battio.battinfo.cap;
|
||||
if(battio.battinfo.state == ACPI_BATT_STAT_INVALID)
|
||||
{
|
||||
@@ -68,13 +70,26 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
|
||||
#ifdef ACPIIO_BATT_GET_BIX
|
||||
battio.unit = i;
|
||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BIX, &battio) >= 0)
|
||||
{
|
||||
ffStrbufAppendS(&battery->manufacturer, battio.bix.oeminfo);
|
||||
ffStrbufAppendS(&battery->modelName, battio.bix.model);
|
||||
ffStrbufAppendS(&battery->technology, battio.bix.type);
|
||||
ffStrbufAppendS(&battery->serial, battio.bix.serial);
|
||||
battery->cycleCount = battio.bix.cycles;
|
||||
}
|
||||
#elif defined(ACPIIO_BATT_GET_BIF)
|
||||
battio.unit = i;
|
||||
if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) >= 0)
|
||||
{
|
||||
ffStrbufAppendS(&battery->manufacturer, battio.bif.oeminfo);
|
||||
ffStrbufAppendS(&battery->modelName, battio.bif.model);
|
||||
ffStrbufAppendS(&battery->technology, battio.bif.type);
|
||||
ffStrbufAppendS(&battery->serial, battio.bif.serial);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,47 @@
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
#include "detection/temps/temps_linux.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power
|
||||
|
||||
static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
static bool checkAc(const char* id, FFstrbuf* tmpBuffer)
|
||||
{
|
||||
uint32_t dirLength = dir->length;
|
||||
if (ffStrStartsWith(id, "BAT"))
|
||||
ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/ADP1/online");
|
||||
else if (ffStrStartsWith(id, "macsmc-battery"))
|
||||
ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/macsmc-ac/online");
|
||||
else
|
||||
ffStrbufClear(tmpBuffer);
|
||||
|
||||
char online = '\0';
|
||||
return ffReadFileData(tmpBuffer->chars, 1, &online) == 1 && online == '1';
|
||||
}
|
||||
|
||||
static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate();
|
||||
|
||||
//type must exist and be "Battery"
|
||||
ffStrbufAppendS(dir, "/type");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
// type must exist and be "Battery"
|
||||
if (!ffReadFileBufferRelative(dfd, "type", &tmpBuffer))
|
||||
return;
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery"))
|
||||
return;
|
||||
|
||||
//scope may not exist or must not be "Device"
|
||||
ffStrbufAppendS(dir, "/scope");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
// scope may not exist or must not be "Device"
|
||||
if (ffReadFileBufferRelative(dfd, "scope", &tmpBuffer))
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device"))
|
||||
return;
|
||||
|
||||
//capacity must exist and be not empty
|
||||
ffStrbufAppendS(dir, "/capacity");
|
||||
bool available = ffReadFileBuffer(dir->chars, &tmpBuffer); // This is expensive in my laptop
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
if (!available)
|
||||
// capacity must exist and be not empty
|
||||
// This is expensive in my laptop
|
||||
if (!ffReadFileBufferRelative(dfd, "capacity", &tmpBuffer))
|
||||
return;
|
||||
|
||||
FFBatteryResult* result = ffListAdd(results);
|
||||
@@ -45,39 +50,63 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
//At this point, we have a battery. Try to get as much values as possible.
|
||||
|
||||
ffStrbufInit(&result->manufacturer);
|
||||
ffStrbufAppendS(dir, "/manufacturer");
|
||||
if (ffReadFileBuffer(dir->chars, &result->manufacturer))
|
||||
if (ffReadFileBufferRelative(dfd, "manufacturer", &result->manufacturer))
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
else if (ffStrEquals(id, "macsmc-battery")) // asahi
|
||||
ffStrbufSetStatic(&result->manufacturer, "Apple Inc.");
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->modelName);
|
||||
ffStrbufAppendS(dir, "/model_name");
|
||||
if (ffReadFileBuffer(dir->chars, &result->modelName))
|
||||
if (ffReadFileBufferRelative(dfd, "model_name", &result->modelName))
|
||||
ffStrbufTrimRightSpace(&result->modelName);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->technology);
|
||||
ffStrbufAppendS(dir, "/technology");
|
||||
if (ffReadFileBuffer(dir->chars, &result->technology))
|
||||
if (ffReadFileBufferRelative(dfd, "technology", &result->technology))
|
||||
ffStrbufTrimRightSpace(&result->technology);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->status);
|
||||
ffStrbufAppendS(dir, "/status");
|
||||
if (ffReadFileBuffer(dir->chars, &result->status))
|
||||
if (ffReadFileBufferRelative(dfd, "status", &result->status))
|
||||
ffStrbufTrimRightSpace(&result->status);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
// Unknown, Charging, Discharging, Not charging, Full
|
||||
if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
|
||||
ffStrbufSetStatic(&result->status, "AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Unknown"))
|
||||
ffStrbufClear(&result->status);
|
||||
|
||||
ffStrbufAppendS(dir, "/capacity_level");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
result->timeRemaining = -1;
|
||||
if (ffStrbufEqualS(&result->status, "Discharging"))
|
||||
{
|
||||
if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &tmpBuffer))
|
||||
result->timeRemaining = (int32_t) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
else
|
||||
{
|
||||
if (ffReadFileBufferRelative(dfd, "charge_now", &tmpBuffer))
|
||||
{
|
||||
int64_t chargeNow = ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (chargeNow > 0)
|
||||
{
|
||||
if (ffReadFileBufferRelative(dfd, "current_now", &tmpBuffer))
|
||||
{
|
||||
int64_t currentNow = ffStrbufToSInt(&tmpBuffer, INT64_MIN);
|
||||
if (currentNow < 0) currentNow = -currentNow;
|
||||
if (currentNow > 0)
|
||||
result->timeRemaining = (int32_t) ((chargeNow * 3600) / currentNow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checkAc(id, &tmpBuffer))
|
||||
ffStrbufAppendS(&result->status, ", AC Connected");
|
||||
}
|
||||
else if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full"))
|
||||
ffStrbufSetStatic(&result->status, "AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Charging"))
|
||||
ffStrbufAppendS(&result->status, ", AC Connected");
|
||||
else if (ffStrbufEqualS(&result->status, "Unknown"))
|
||||
{
|
||||
ffStrbufClear(&result->status);
|
||||
if (checkAc(id, &tmpBuffer))
|
||||
ffStrbufAppendS(&result->status, "AC Connected");
|
||||
}
|
||||
|
||||
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
|
||||
@@ -88,50 +117,33 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
ffStrbufSetStatic(&result->status, "Critical");
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufInit(&result->serial);
|
||||
ffStrbufAppendS(dir, "/serial_number");
|
||||
if (ffReadFileBuffer(dir->chars, &result->serial))
|
||||
if (ffReadFileBufferRelative(dfd, "serial_number", &result->serial))
|
||||
ffStrbufTrimRightSpace(&result->serial);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
|
||||
ffStrbufAppendS(dir, "/cycle_count");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
if (ffReadFileBufferRelative(dfd, "cycle_count", &tmpBuffer))
|
||||
{
|
||||
int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0);
|
||||
result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount;
|
||||
}
|
||||
|
||||
ffStrbufInit(&result->manufactureDate);
|
||||
ffStrbufAppendS(dir, "/manufacture_year");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
if (ffReadFileBufferRelative(dfd, "manufacture_year", &tmpBuffer))
|
||||
{
|
||||
int year = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (year > 0)
|
||||
{
|
||||
ffStrbufAppendS(dir, "/manufacture_month");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
if (ffReadFileBufferRelative(dfd, "manufacture_month", &tmpBuffer))
|
||||
{
|
||||
int month = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (month > 0)
|
||||
{
|
||||
ffStrbufAppendS(dir, "/manufacture_day");
|
||||
available = ffReadFileBuffer(dir->chars, &tmpBuffer);
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
if (available)
|
||||
if (ffReadFileBufferRelative(dfd, "manufacture_day", &tmpBuffer))
|
||||
{
|
||||
int day = (int) ffStrbufToSInt(&tmpBuffer, 0);
|
||||
if (day > 0)
|
||||
{
|
||||
ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,33 +153,25 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option
|
||||
result->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
if (options->temp)
|
||||
{
|
||||
ffStrbufAppendS(dir, "/temp");
|
||||
if (ffReadFileBuffer(dir->chars, &tmpBuffer))
|
||||
if (ffReadFileBufferRelative(dfd, "temp", &tmpBuffer))
|
||||
result->temperature = ffStrbufToDouble(&tmpBuffer) / 10;
|
||||
ffStrbufSubstrBefore(dir, dirLength);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&baseDir, "/sys/class/power_supply/");
|
||||
|
||||
uint32_t baseDirLength = baseDir.length;
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars);
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/power_supply/");
|
||||
if(dirp == NULL)
|
||||
return "opendir(\"/sys/class/power_supply/\") == NULL";
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, ".."))
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&baseDir, entry->d_name);
|
||||
parseBattery(&baseDir, entry->d_name, options, results);
|
||||
ffStrbufSubstrBefore(&baseDir, baseDirLength);
|
||||
FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
|
||||
if (dfd > 0) parseBattery(dfd, entry->d_name, options, results);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <prop/prop_array.h>
|
||||
#include <prop/prop_bool.h>
|
||||
#include <prop/prop_dictionary.h>
|
||||
#include <prop/prop_object.h>
|
||||
#include <sys/envsys.h>
|
||||
#include <prop/proplib.h>
|
||||
#include <paths.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
|
||||
|
||||
prop_dictionary_t root = NULL;
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
|
||||
|
||||
bool acConnected = false;
|
||||
{
|
||||
prop_array_t acad = prop_dictionary_get(root, "acpiacad0");
|
||||
if (acad)
|
||||
{
|
||||
prop_dictionary_t dict = prop_array_get(acad, 0);
|
||||
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &acConnected);
|
||||
}
|
||||
}
|
||||
|
||||
prop_object_iterator_t itKey = prop_dictionary_iterator(root);
|
||||
for (prop_dictionary_keysym_t key; (key = prop_object_iterator_next(itKey)) != NULL; )
|
||||
{
|
||||
if (!ffStrStartsWith(prop_dictionary_keysym_value(key), "acpibat")) continue;
|
||||
|
||||
prop_array_t bat = prop_dictionary_get_keysym(root, key);
|
||||
uint32_t max = 0, curr = 0, dischargeRate = 0;
|
||||
bool charging = false, critical = false;
|
||||
prop_object_iterator_t iter = prop_array_iterator(bat);
|
||||
for (prop_dictionary_t dict; (dict = prop_object_iterator_next(iter)) != NULL;)
|
||||
{
|
||||
if (prop_object_type(dict) != PROP_TYPE_DICTIONARY)
|
||||
continue;
|
||||
|
||||
const char* desc = NULL;
|
||||
if (!prop_dictionary_get_string(dict, "description", &desc))
|
||||
continue;
|
||||
|
||||
if (ffStrEquals(desc, "present"))
|
||||
{
|
||||
int value = 0;
|
||||
if (prop_dictionary_get_int(dict, "cur-value", &value) && value == 0)
|
||||
continue;
|
||||
}
|
||||
else if (ffStrEquals(desc, "charging"))
|
||||
{
|
||||
prop_dictionary_get_uint8(dict, "cur-value", (uint8_t*) &charging);
|
||||
}
|
||||
else if (ffStrEquals(desc, "charge"))
|
||||
{
|
||||
prop_dictionary_get_uint32(dict, "max-value", &max);
|
||||
prop_dictionary_get_uint32(dict, "cur-value", &curr);
|
||||
const char* state = NULL;
|
||||
if (prop_dictionary_get_string(dict, "state", &state) && ffStrEquals(state, "critical"))
|
||||
critical = true;
|
||||
}
|
||||
else if (ffStrEquals(desc, "discharge rate"))
|
||||
{
|
||||
prop_dictionary_get_uint(dict, "cur-value", &dischargeRate);
|
||||
}
|
||||
}
|
||||
|
||||
if (max > 0)
|
||||
{
|
||||
FFBatteryResult* battery = ffListAdd(results);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
battery->timeRemaining = -1;
|
||||
|
||||
battery->capacity = (double) curr / (double) max * 100.;
|
||||
if (charging)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
else if (dischargeRate)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (critical)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
if (acConnected)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(itKey);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <machine/apmvar.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY);
|
||||
|
||||
if (devfd < 0) return "open(dev/apm, O_RDONLY) failed";
|
||||
|
||||
struct apm_power_info info = {};
|
||||
|
||||
if (ioctl(devfd, APM_IOC_GETPOWER, &info) < 0)
|
||||
return "ioctl(APM_IOC_GETPOWER) failed";
|
||||
|
||||
if (info.battery_state == APM_BATTERY_ABSENT)
|
||||
return NULL;
|
||||
|
||||
FFBatteryResult* battery = (FFBatteryResult*) ffListAdd(result);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
battery->timeRemaining = -1;
|
||||
battery->capacity = info.battery_life;
|
||||
ffStrbufInit(&battery->manufacturer);
|
||||
ffStrbufInit(&battery->modelName);
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInit(&battery->technology);
|
||||
ffStrbufInit(&battery->serial);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
|
||||
if (info.ac_state == APM_AC_ON)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
else if (info.ac_state == APM_AC_BACKUP)
|
||||
ffStrbufAppendS(&battery->status, "Backup In Use");
|
||||
else if (info.ac_state == APM_AC_OFF)
|
||||
{
|
||||
battery->timeRemaining = (int) info.minutes_left * 60;
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
}
|
||||
|
||||
if (info.battery_state == APM_BATT_CRITICAL || info.battery_state == APM_BATT_CHARGING)
|
||||
{
|
||||
if (battery->status.length) ffStrbufAppendS(&battery->status, ", ");
|
||||
ffStrbufAppendS(&battery->status, info.battery_state == APM_BATT_CRITICAL ? "Critical" : "Charging");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -121,6 +121,13 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
battery->temperature = temp / 10.0 - 273.15;
|
||||
}
|
||||
|
||||
{
|
||||
bqi.InformationLevel = BatteryEstimatedTime;
|
||||
ULONG time;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &time, sizeof(time), &dwOut, NULL))
|
||||
battery->timeRemaining = time == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) time;
|
||||
}
|
||||
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
@@ -241,6 +248,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
ffStrbufInit(&battery->serial);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = 0;
|
||||
battery->timeRemaining = info.EstimatedTime == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) info.EstimatedTime;
|
||||
|
||||
battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity;
|
||||
if(info.AcOnLine)
|
||||
@@ -252,6 +260,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
else if(info.Discharging)
|
||||
ffStrbufAppendS(&battery->status, "Discharging");
|
||||
|
||||
|
||||
detectBySmbios(battery);
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -25,7 +25,7 @@ const char* ffDetectBios(FFBiosResult* result)
|
||||
{
|
||||
ffStrbufSetStatic(&result->type,
|
||||
ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) ||
|
||||
ffPathExists("/boot/efi/efi" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
|
||||
ffPathExists("/boot/efi/efi/" /*efi partition*/, FF_PATHTYPE_DIRECTORY)
|
||||
? "UEFI" : "BIOS");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const char *ffDetectBios(FFBiosResult *bios)
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version);
|
||||
if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE))
|
||||
if (ffPathExists("/sys/firmware/efi/", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE))
|
||||
ffStrbufSetStatic(&bios->type, "UEFI");
|
||||
else
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "bios.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.dmi.bios-date", &bios->date) == NULL)
|
||||
ffCleanUpSmbiosValue(&bios->date);
|
||||
if (ffSysctlGetString("machdep.dmi.bios-version", &bios->version) == NULL)
|
||||
ffCleanUpSmbiosValue(&bios->version);
|
||||
if (ffSysctlGetString("machdep.dmi.bios-vendor", &bios->vendor) == NULL)
|
||||
ffCleanUpSmbiosValue(&bios->vendor);
|
||||
ffSysctlGetString("machdep.bootmethod", &bios->type);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "bios.h"
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
const char* ffDetectBios(FF_MAYBE_UNUSED FFBiosResult* bios)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@ typedef struct FFBluetoothResult
|
||||
bool connected;
|
||||
} FFBluetoothResult;
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */);
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
@interface IOBluetoothDevice()
|
||||
@property (nonatomic) uint8_t batteryPercentCase;
|
||||
@property (nonatomic) uint8_t batteryPercentCombined;
|
||||
@property (nonatomic) uint8_t batteryPercentLeft;
|
||||
@property (nonatomic) uint8_t batteryPercentRight;
|
||||
@property (nonatomic) uint8_t batteryPercentSingle;
|
||||
@end
|
||||
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
|
||||
if(!ioDevices)
|
||||
@@ -10,11 +18,23 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
|
||||
for(IOBluetoothDevice* ioDevice in ioDevices)
|
||||
{
|
||||
if (!options->showDisconnected && !ioDevice.isConnected)
|
||||
continue;
|
||||
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, ioDevice.name.UTF8String);
|
||||
ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String);
|
||||
ffStrbufReplaceAllC(&device->address, '-', ':');
|
||||
ffStrbufUpperCase(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
|
||||
if (ioDevice.batteryPercentSingle)
|
||||
device->battery = ioDevice.batteryPercentSingle;
|
||||
else if (ioDevice.batteryPercentCombined)
|
||||
device->battery = ioDevice.batteryPercentCombined;
|
||||
else if (ioDevice.batteryPercentCase)
|
||||
device->battery = ioDevice.batteryPercentCase;
|
||||
|
||||
device->connected = !!ioDevice.isConnected;
|
||||
if(ioDevice.serviceClassMajor & kBluetoothServiceClassMajorLimitedDiscoverableMode)
|
||||
ffStrbufAppendS(&device->type, "Limited Discoverable Mode, ");
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
#define L2CAP_SOCKET_CHECKED
|
||||
#include <bluetooth.h>
|
||||
|
||||
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
|
||||
{
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, bt_devremote_name_gen(dev->devname, &dev->bdaddr));
|
||||
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
|
||||
ffStrbufUpperCase(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
// struct hostent* ent = bt_gethostent();
|
||||
if (bt_devenum((void*) enumDev, devices) < 0)
|
||||
return "bt_devenum() failed";
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
/* Example dbus reply, striped to only the relevant parts:
|
||||
array [ //root
|
||||
@@ -44,16 +45,16 @@ array [ //root
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
|
||||
static bool detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
return true;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
return true;
|
||||
|
||||
const char* deviceProperty;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
|
||||
@@ -74,6 +75,13 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
|
||||
}
|
||||
else if(ffStrEquals(deviceProperty, "Connected"))
|
||||
ffDBusGetBool(dbus, &dictIter, &device->connected);
|
||||
else if(ffStrEquals(deviceProperty, "Paired"))
|
||||
{
|
||||
bool paired = true;
|
||||
ffDBusGetBool(dbus, &dictIter, &paired);
|
||||
if (!paired) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device)
|
||||
@@ -103,32 +111,37 @@ static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFB
|
||||
|
||||
do
|
||||
{
|
||||
detectBluetoothValue(dbus, &arrayIter, device);
|
||||
bool shouldContinue = detectBluetoothValue(dbus, &arrayIter, device);
|
||||
if (!shouldContinue)
|
||||
{
|
||||
ffStrbufClear(&device->name);
|
||||
break;
|
||||
}
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
}
|
||||
|
||||
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
static FFBluetoothResult* detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
const char* objectPath;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
||||
|
||||
// We don't want adapter objects
|
||||
if(!ffStrContains(objectPath, "/dev_"))
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
@@ -145,16 +158,10 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage
|
||||
detectBluetoothProperty(dbus, &arrayIter, device);
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
|
||||
if(device->name.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
ffStrbufDestroy(&device->type);
|
||||
--devices->length;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter, int32_t connectedCount)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
@@ -164,11 +171,25 @@ static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIt
|
||||
|
||||
do
|
||||
{
|
||||
detectBluetoothObject(devices, dbus, &arrayIter);
|
||||
FFBluetoothResult* device = detectBluetoothObject(devices, dbus, &arrayIter);
|
||||
|
||||
if (device)
|
||||
{
|
||||
if(device->name.length == 0 || (connectedCount > 0 && !device->connected))
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
ffStrbufDestroy(&device->type);
|
||||
--devices->length;
|
||||
}
|
||||
|
||||
if (device->connected && --connectedCount == 0)
|
||||
break;
|
||||
}
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
}
|
||||
|
||||
static const char* detectBluetooth(FFlist* devices)
|
||||
static const char* detectBluetooth(FFlist* devices, int32_t connectedCount)
|
||||
{
|
||||
FFDBusData dbus;
|
||||
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
|
||||
@@ -186,18 +207,43 @@ static const char* detectBluetooth(FFlist* devices)
|
||||
return "Failed to get root iterator of GetManagedObjects";
|
||||
}
|
||||
|
||||
detectBluetoothRoot(devices, &dbus, &rootIter);
|
||||
detectBluetoothRoot(devices, &dbus, &rootIter, connectedCount);
|
||||
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint32_t connectedDevices(void)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
|
||||
if(dirp == NULL)
|
||||
return 0;
|
||||
|
||||
uint32_t result = 0;
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (strchr(entry->d_name, ':') != NULL)
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
return detectBluetooth(devices);
|
||||
int32_t connectedCount = -1;
|
||||
if (!options->showDisconnected)
|
||||
{
|
||||
connectedCount = (int32_t) connectedDevices();
|
||||
if (connectedCount == 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return detectBluetooth(devices, connectedCount);
|
||||
#else
|
||||
return "Fastfetch was compiled without DBus support";
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "bluetooth.h"
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wpointer-sign"
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
// Actually bluetoothapis.dll, but it's missing on Windows 7
|
||||
FF_LIBRARY_LOAD(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
|
||||
FF_LIBRARY_LOAD(bluetoothapis, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstDevice)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextDevice)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindDeviceClose)
|
||||
@@ -20,26 +20,27 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
};
|
||||
HBLUETOOTH_DEVICE_FIND hFind = ffBluetoothFindFirstDevice(&(BLUETOOTH_DEVICE_SEARCH_PARAMS) {
|
||||
.fReturnConnected = TRUE,
|
||||
.fReturnRemembered = TRUE,
|
||||
.fReturnAuthenticated = TRUE,
|
||||
.fReturnUnknown = TRUE,
|
||||
.fReturnRemembered = options->showDisconnected,
|
||||
.fReturnAuthenticated = options->showDisconnected,
|
||||
.dwSize = sizeof(BLUETOOTH_DEVICE_SEARCH_PARAMS)
|
||||
}, &btdi);
|
||||
if(!hFind)
|
||||
{
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
return NULL;
|
||||
return "BluetoothFindFirstDevice() failed";
|
||||
}
|
||||
|
||||
do {
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInitWS(&device->name, btdi.szName);
|
||||
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
btdi.Address.rgBytes[0],
|
||||
btdi.Address.rgBytes[1],
|
||||
btdi.Address.rgBytes[2],
|
||||
btdi.Address.rgBytes[3],
|
||||
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
btdi.Address.rgBytes[5],
|
||||
btdi.Address.rgBytes[4],
|
||||
btdi.Address.rgBytes[5]);
|
||||
btdi.Address.rgBytes[3],
|
||||
btdi.Address.rgBytes[2],
|
||||
btdi.Address.rgBytes[1],
|
||||
btdi.Address.rgBytes[0]);
|
||||
ffStrbufInit(&device->type);
|
||||
device->battery = 0;
|
||||
device->connected = !!btdi.fConnected;
|
||||
@@ -121,5 +122,8 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
|
||||
ffBluetoothFindDeviceClose(hFind);
|
||||
|
||||
const char* ffBluetoothDetectBattery(FFlist* result);
|
||||
ffBluetoothDetectBattery(devices);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "bluetooth.h"
|
||||
}
|
||||
#include "util/windows/wmi.hpp"
|
||||
#include "util/windows/unicode.hpp"
|
||||
|
||||
STDAPI InitVariantFromStringArray(_In_reads_(cElems) PCWSTR *prgsz, _In_ ULONG cElems, _Out_ VARIANT *pvar);
|
||||
|
||||
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* ffBluetoothDetectBattery(FFlist* devices)
|
||||
{
|
||||
FFWmiQuery query(L"SELECT __PATH FROM Win32_PnPEntity WHERE Service = 'BthHFEnum'", nullptr, FFWmiNamespace::CIMV2);
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
IWbemClassObject* pInParams = nullptr;
|
||||
on_scope_exit releaseInParams([&] { pInParams && pInParams->Release(); });
|
||||
{
|
||||
IWbemClassObject* pnpEntityClass = nullptr;
|
||||
|
||||
if (FAILED(query.pService->GetObjectW(bstr_t(L"Win32_PnPEntity"), 0, nullptr, &pnpEntityClass, nullptr)))
|
||||
return "Failed to get PnP entity class";
|
||||
on_scope_exit releasePnpEntityClass([&] { pnpEntityClass && pnpEntityClass->Release(); });
|
||||
|
||||
if (FAILED(pnpEntityClass->GetMethod(bstr_t(L"GetDeviceProperties"), 0, &pInParams, NULL)))
|
||||
return "Failed to get GetDeviceProperties method";
|
||||
|
||||
VARIANT devicePropertyKeys;
|
||||
PCWSTR props[] = { L"{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2", L"DEVPKEY_Bluetooth_DeviceAddress" };
|
||||
|
||||
if (FAILED(InitVariantFromStringArray(props, ARRAY_SIZE(props), &devicePropertyKeys)))
|
||||
return "Failed to init variant from string array";
|
||||
on_scope_exit releaseDevicePropertyKeys([&] { VariantClear(&devicePropertyKeys); });
|
||||
|
||||
if (FAILED(pInParams->Put(L"devicePropertyKeys", 0, &devicePropertyKeys, CIM_FLAG_ARRAY | CIM_STRING)))
|
||||
return "Failed to put devicePropertyKeys";
|
||||
}
|
||||
|
||||
while (FFWmiRecord record = query.next())
|
||||
{
|
||||
IWbemCallResult* pCallResult = nullptr;
|
||||
|
||||
if (FAILED(query.pService->ExecMethod(record.get(L"__PATH").bstrVal, bstr_t(L"GetDeviceProperties"), 0, nullptr, pInParams, nullptr, &pCallResult)))
|
||||
continue;
|
||||
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
|
||||
|
||||
IWbemClassObject* pResultObject = nullptr;
|
||||
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject)))
|
||||
continue;
|
||||
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
|
||||
|
||||
VARIANT propArray;
|
||||
if (FAILED(pResultObject->Get(L"deviceProperties", 0, &propArray, nullptr, nullptr)))
|
||||
continue;
|
||||
on_scope_exit releasePropArray([&] { VariantClear(&propArray); });
|
||||
|
||||
if (propArray.vt != (VT_ARRAY | VT_UNKNOWN) ||
|
||||
(propArray.parray->fFeatures & FADF_UNKNOWN) == 0 ||
|
||||
propArray.parray->cDims != 1 ||
|
||||
propArray.parray->rgsabound[0].cElements != 2
|
||||
)
|
||||
continue;
|
||||
|
||||
uint8_t batt = 0;
|
||||
for (LONG i = 0; i < 2; i++)
|
||||
{
|
||||
IWbemClassObject* object = nullptr;
|
||||
if (FAILED(SafeArrayGetElement(propArray.parray, &i, &object)))
|
||||
continue;
|
||||
|
||||
FFWmiRecord rec(object);
|
||||
auto data = rec.get(L"Data");
|
||||
if (data.vt == VT_EMPTY)
|
||||
break;
|
||||
|
||||
if (i == 0)
|
||||
batt = data.get<uint8_t>();
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY addr; // MAC address without colon
|
||||
ffStrbufInitWSV(&addr, data.get<std::wstring_view>());
|
||||
if (__builtin_expect(addr.length != 12, 0))
|
||||
continue;
|
||||
|
||||
FF_LIST_FOR_EACH(FFBluetoothResult, bt, *devices)
|
||||
{
|
||||
if (bt->address.length != 12 + 5)
|
||||
continue;
|
||||
|
||||
if (addr.chars[0] == bt->address.chars[0] &&
|
||||
addr.chars[1] == bt->address.chars[1] &&
|
||||
addr.chars[2] == bt->address.chars[3] &&
|
||||
addr.chars[3] == bt->address.chars[4] &&
|
||||
addr.chars[4] == bt->address.chars[6] &&
|
||||
addr.chars[5] == bt->address.chars[7] &&
|
||||
addr.chars[6] == bt->address.chars[9] &&
|
||||
addr.chars[7] == bt->address.chars[10] &&
|
||||
addr.chars[8] == bt->address.chars[12] &&
|
||||
addr.chars[9] == bt->address.chars[13] &&
|
||||
addr.chars[10] == bt->address.chars[15] &&
|
||||
addr.chars[11] == bt->address.chars[16])
|
||||
{
|
||||
bt->battery = batt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -3,56 +3,47 @@
|
||||
|
||||
#ifdef FF_HAVE_DBUS
|
||||
#include "common/dbus.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
/* Example dbus reply, striped to only the relevant parts:
|
||||
array [ //root
|
||||
/* Example dbus reply:
|
||||
array [
|
||||
dict entry(
|
||||
object path "/org/bluez/hci0"
|
||||
array [
|
||||
dict entry(
|
||||
string "org.bluez.Adapter1"
|
||||
array [
|
||||
dict entry(
|
||||
string "Address"
|
||||
variant string "XX:XX:XX:XX:XX:XX"
|
||||
)
|
||||
dict entry(
|
||||
string "Name"
|
||||
variant string "xxxxxxxx"
|
||||
)
|
||||
dict entry(
|
||||
string "Powered"
|
||||
variant boolean true
|
||||
)
|
||||
dict entry(
|
||||
string "PowerState"
|
||||
variant string "on"
|
||||
)
|
||||
dict entry(
|
||||
string "Manufacturer"
|
||||
variant uint16 2
|
||||
)
|
||||
dict entry(
|
||||
string "Version"
|
||||
variant byte 12
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
string "Address"
|
||||
variant string "XX:XX:XX:XX:XX:XX"
|
||||
)
|
||||
dict entry(
|
||||
string "Name"
|
||||
variant string "xxxxxxxx"
|
||||
)
|
||||
dict entry(
|
||||
string "Powered"
|
||||
variant boolean true
|
||||
)
|
||||
dict entry(
|
||||
string "PowerState"
|
||||
variant string "on"
|
||||
)
|
||||
dict entry(
|
||||
string "Manufacturer"
|
||||
variant uint16 2
|
||||
)
|
||||
dict entry(
|
||||
string "Version"
|
||||
variant byte 12
|
||||
)
|
||||
]
|
||||
*/
|
||||
|
||||
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
|
||||
static const char* detectBluetoothProperty(FFBluetoothRadioResult* device, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
return "Expected dict entry";
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
return "Expected dict entry key to be a string";
|
||||
|
||||
const char* deviceProperty;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
|
||||
@@ -77,121 +68,73 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue
|
||||
ffDBusGetBool(dbus, &dictIter, &device->discoverable);
|
||||
else if(ffStrEquals(deviceProperty, "Pairable"))
|
||||
ffDBusGetBool(dbus, &dictIter, &device->connectable);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothRadioResult* device)
|
||||
static const char* detectBluetoothRoot(FFBluetoothRadioResult* device, const char* hciName, FFDBusData* dbus)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
char objPath[300];
|
||||
snprintf(objPath, sizeof(objPath), "/org/bluez/%s", hciName);
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
DBusMessage* properties = ffDBusGetMethodReply(dbus, "org.bluez", objPath, "org.freedesktop.DBus.Properties", "GetAll", "org.bluez.Adapter1");
|
||||
if(!properties)
|
||||
return "Failed to call org.freedesktop.DBus.Properties.GetAll";
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
||||
return;
|
||||
|
||||
const char* propertyType;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
|
||||
|
||||
if(!ffStrContains(propertyType, ".Adapter"))
|
||||
return; //We don't care about other properties
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
do
|
||||
DBusMessageIter rootIter;
|
||||
if(!dbus->lib->ffdbus_message_iter_init(properties, &rootIter))
|
||||
{
|
||||
detectBluetoothValue(dbus, &arrayIter, device);
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
}
|
||||
|
||||
static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
||||
return;
|
||||
|
||||
DBusMessageIter dictIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
||||
return;
|
||||
|
||||
const char* objectPath;
|
||||
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
||||
|
||||
//We want adapter objects
|
||||
if(!ffStrStartsWith(objectPath, "/org/bluez/hci") || ffStrContains(objectPath, "/dev_"))
|
||||
return;
|
||||
|
||||
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
||||
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
||||
|
||||
FFBluetoothRadioResult* device = ffListAdd(devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInitStatic(&device->vendor, "Unknown");
|
||||
device->lmpVersion = INT_MIN;
|
||||
device->lmpSubversion = INT_MIN;
|
||||
device->enabled = false;
|
||||
|
||||
do
|
||||
{
|
||||
detectBluetoothProperty(dbus, &arrayIter, device);
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
|
||||
if(device->name.length == 0)
|
||||
{
|
||||
ffStrbufDestroy(&device->name);
|
||||
ffStrbufDestroy(&device->address);
|
||||
--devices->length;
|
||||
dbus->lib->ffdbus_message_unref(properties);
|
||||
return "Failed to get root iterator of org.freedesktop.DBus.Properties.GetAll";
|
||||
}
|
||||
}
|
||||
|
||||
static void detectBluetoothRoot(FFlist* devices, FFDBusData* dbus, DBusMessageIter* iter)
|
||||
{
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
||||
return;
|
||||
if(dbus->lib->ffdbus_message_iter_get_arg_type(&rootIter) != DBUS_TYPE_ARRAY)
|
||||
{
|
||||
dbus->lib->ffdbus_message_unref(properties);
|
||||
return "Expected array";
|
||||
}
|
||||
|
||||
DBusMessageIter arrayIter;
|
||||
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
|
||||
dbus->lib->ffdbus_message_iter_recurse(&rootIter, &arrayIter);
|
||||
|
||||
do
|
||||
{
|
||||
detectBluetoothObject(devices, dbus, &arrayIter);
|
||||
detectBluetoothProperty(device, dbus, &arrayIter);
|
||||
} while (dbus->lib->ffdbus_message_iter_next(&arrayIter));
|
||||
|
||||
dbus->lib->ffdbus_message_unref(properties);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectBluetooth(FFlist* devices)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/bluetooth");
|
||||
if(dirp == NULL)
|
||||
return "Failed to open /sys/class/bluetooth";
|
||||
|
||||
FFDBusData dbus;
|
||||
const char* error = ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus);
|
||||
if(error)
|
||||
return error;
|
||||
|
||||
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", NULL);
|
||||
if(!managedObjects)
|
||||
return "Failed to call GetManagedObjects";
|
||||
|
||||
DBusMessageIter rootIter;
|
||||
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return "Failed to get root iterator of GetManagedObjects";
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (strchr(entry->d_name, ':') != NULL) // ignore connected devices
|
||||
continue;
|
||||
|
||||
FFBluetoothRadioResult* device = ffListAdd(devices);
|
||||
ffStrbufInit(&device->name);
|
||||
ffStrbufInit(&device->address);
|
||||
ffStrbufInitStatic(&device->vendor, "Unknown");
|
||||
device->lmpVersion = INT_MIN;
|
||||
device->lmpSubversion = INT_MIN;
|
||||
device->enabled = false;
|
||||
detectBluetoothRoot(device, entry->d_name, &dbus);
|
||||
}
|
||||
|
||||
detectBluetoothRoot(devices, &dbus, &rootIter);
|
||||
|
||||
dbus.lib->ffdbus_message_unref(managedObjects);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -202,6 +145,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
#ifdef FF_HAVE_DBUS
|
||||
return detectBluetooth(devices);
|
||||
#else
|
||||
FF_UNUSED(devices)
|
||||
return "Fastfetch was compiled without DBus support";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ static_assert(sizeof(BTH_LOCAL_RADIO_INFO) == 292, "BTH_LOCAL_RADIO_INFO should
|
||||
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
{
|
||||
// Actually bluetoothapis.dll, but it's missing on Windows 7
|
||||
FF_LIBRARY_LOAD(bluetoothapis, NULL, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
|
||||
FF_LIBRARY_LOAD(bluetoothapis, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindFirstRadio)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindNextRadio)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(bluetoothapis, BluetoothFindRadioClose)
|
||||
@@ -84,12 +84,12 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
|
||||
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
|
||||
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
addr.rgBytes[0],
|
||||
addr.rgBytes[1],
|
||||
addr.rgBytes[2],
|
||||
addr.rgBytes[3],
|
||||
addr.rgBytes[5],
|
||||
addr.rgBytes[4],
|
||||
addr.rgBytes[5]);
|
||||
addr.rgBytes[3],
|
||||
addr.rgBytes[2],
|
||||
addr.rgBytes[1],
|
||||
addr.rgBytes[0]);
|
||||
|
||||
device->lmpVersion = blri.radioInfo.lmpVersion;
|
||||
device->lmpSubversion = blri.radioInfo.lmpSubversion;
|
||||
|
||||
@@ -6,9 +6,25 @@
|
||||
|
||||
const char* ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
|
||||
if (ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name))
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_serial", "/sys/class/dmi/id/board_serial", &board->serial);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version);
|
||||
}
|
||||
else if (ffReadFileBuffer("/proc/device-tree/board", &board->name))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&board->name);
|
||||
}
|
||||
else if (ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor))
|
||||
{
|
||||
uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ',');
|
||||
if (comma < board->vendor.length)
|
||||
{
|
||||
ffStrbufSetS(&board->name, board->vendor.chars + comma + 1);
|
||||
ffStrbufTrimRightSpace(&board->name);
|
||||
ffStrbufSubstrBefore(&board->vendor, comma);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "board.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectBoard(FFBoardResult* board)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.dmi.board-product", &board->name) == NULL)
|
||||
ffCleanUpSmbiosValue(&board->name);
|
||||
if (ffSysctlGetString("machdep.dmi.board-version", &board->version) == NULL)
|
||||
ffCleanUpSmbiosValue(&board->version);
|
||||
if (ffSysctlGetString("machdep.dmi.board-vendor", &board->vendor) == NULL)
|
||||
ffCleanUpSmbiosValue(&board->vendor);
|
||||
if (ffSysctlGetString("machdep.dmi.board-serial", &board->serial) == NULL)
|
||||
ffCleanUpSmbiosValue(&board->serial);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -34,9 +34,9 @@ bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* resu
|
||||
ffEfiUcs2ToUtf8(efiOption->Description, &result->name);
|
||||
|
||||
for (
|
||||
ffEfiDevicePathProtocol* filePathList = (void*) &efiOption->Description[descLen + 1];
|
||||
ffEfiDevicePathProtocol* filePathList = (ffEfiDevicePathProtocol*) &efiOption->Description[descLen + 1];
|
||||
filePathList->Type != 0x7F; // End of Hardware Device Path
|
||||
filePathList = (void*) ((uint8_t*) filePathList + filePathList->Length))
|
||||
filePathList = (ffEfiDevicePathProtocol*) ((uint8_t*) filePathList + filePathList->Length))
|
||||
{
|
||||
if (filePathList->Type == 4 && filePathList->SubType == 4)
|
||||
{
|
||||
|
||||
@@ -38,9 +38,9 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
|
||||
uint8_t buffer[2048];
|
||||
wchar_t key[16];
|
||||
wsprintfW(key, L"Boot%04X", value);
|
||||
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", value);
|
||||
uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer));
|
||||
if (size < sizeof(FFEfiLoadOption) || size == sizeof(buffer))
|
||||
if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer))
|
||||
return "GetFirmwareEnvironmentVariableW(Boot####) failed";
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
|
||||
|
||||
@@ -92,13 +92,13 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
|
||||
|
||||
for (uint32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn));
|
||||
IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, ARRAY_SIZE(i2cIn));
|
||||
usleep(options->ddcciSleep * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t i2cOut[12] = {};
|
||||
if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, sizeof(i2cOut)) == KERN_SUCCESS)
|
||||
if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, ARRAY_SIZE(i2cOut)) == KERN_SUCCESS)
|
||||
{
|
||||
if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00)
|
||||
continue;
|
||||
@@ -113,7 +113,7 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult*
|
||||
ffStrbufInit(&brightness->name);
|
||||
|
||||
uint8_t edid[128] = {};
|
||||
if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, sizeof(edid)) == KERN_SUCCESS)
|
||||
if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, ARRAY_SIZE(edid)) == KERN_SUCCESS)
|
||||
ffEdidGetName(edid, &brightness->name);
|
||||
}
|
||||
}
|
||||
@@ -155,12 +155,12 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F
|
||||
.sendAddress = 0x6e,
|
||||
.sendTransactionType = kIOI2CSimpleTransactionType,
|
||||
.sendBuffer = (vm_address_t) i2cIn,
|
||||
.sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]),
|
||||
.sendBytes = ARRAY_SIZE(i2cIn),
|
||||
.minReplyDelay = options->ddcciSleep,
|
||||
.replyAddress = 0x6F,
|
||||
.replySubAddress = 0x51,
|
||||
.replyTransactionType = kIOI2CDDCciReplyTransactionType,
|
||||
.replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]),
|
||||
.replyBytes = ARRAY_SIZE(i2cOut),
|
||||
.replyBuffer = (vm_address_t) i2cOut,
|
||||
};
|
||||
IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request);
|
||||
|
||||
@@ -16,7 +16,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
|
||||
for (char i = '0'; i <= '9'; ++i)
|
||||
{
|
||||
path[sizeof(path) - 2] = i;
|
||||
path[ARRAY_SIZE(path) - 2] = i;
|
||||
|
||||
FF_AUTO_CLOSE_FD int blfd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (blfd < 0)
|
||||
@@ -34,7 +34,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
brightness->current = status.brightness;
|
||||
|
||||
struct backlight_info info;
|
||||
if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0)
|
||||
if(ioctl(blfd, BACKLIGHTGETINFO, &info) == 0)
|
||||
ffStrbufAppendS(&brightness->name, info.name);
|
||||
else
|
||||
ffStrbufAppendS(&brightness->name, path + strlen("/dev/backlight/"));
|
||||
|
||||
@@ -25,7 +25,7 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, ".."))
|
||||
if(entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&backlightDir, entry->d_name);
|
||||
@@ -48,7 +48,7 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
// if we managed to get edid, use it
|
||||
ffStrbufAppendS(&brightness->name, "/edid");
|
||||
uint8_t edidData[128];
|
||||
if(ffReadFileData(brightness->name.chars, sizeof(edidData), edidData) == sizeof(edidData))
|
||||
if(ffReadFileData(brightness->name.chars, ARRAY_SIZE(edidData), edidData) == ARRAY_SIZE(edidData))
|
||||
{
|
||||
ffStrbufClear(&brightness->name);
|
||||
ffEdidGetName(edidData, &brightness->name);
|
||||
@@ -99,9 +99,9 @@ double ddca_set_default_sleep_multiplier(double multiplier); // ddcutil 1.4
|
||||
DDCA_Status ddca_init(const char *libopts, int syslog_level, int opts);
|
||||
#endif
|
||||
|
||||
static const char* detectWithDdcci(FFBrightnessOptions* options, FFlist* result)
|
||||
static const char* detectWithDdcci(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libddcutil, &instance.config.library.libDdcutil, "dlopen ddcutil failed", "libddcutil" FF_LIBRARY_EXTENSION, 5);
|
||||
FF_LIBRARY_LOAD(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)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "brightness.h"
|
||||
|
||||
#include "common/sysctl.h"
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
// https://man.netbsd.org/NetBSD-10.1/acpiout.4#DESCRIPTION
|
||||
char key[] = "hw.acpi.acpiout0.brightness";
|
||||
char* pn = key + strlen("hw.acpi.acpiout");
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
*pn = (char) ('0' + i);
|
||||
int value = ffSysctlGetInt(key, -1);
|
||||
if (value == -1) continue;
|
||||
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInitF(&brightness->name, "acpiout%d", i);
|
||||
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "brightness.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int devfd = open("/dev/ttyC0", O_RDONLY);
|
||||
|
||||
if (devfd < 0) return "open(dev/ttyC0, O_RDONLY) failed";
|
||||
|
||||
struct wsdisplay_param param = {
|
||||
.param = WSDISPLAYIO_PARAM_BRIGHTNESS,
|
||||
};
|
||||
|
||||
if (ioctl(devfd, WSDISPLAYIO_GETPARAM, ¶m) < 0)
|
||||
return "ioctl(WSDISPLAYIO_GETPARAM) failed";
|
||||
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufInitStatic(&brightness->name, "wsdisplay");
|
||||
|
||||
brightness->max = param.max;
|
||||
brightness->min = param.min;
|
||||
brightness->current = param.curval;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ static const char* detectWithWmi(FFlist* result)
|
||||
|
||||
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(dxva2, NULL, "dlopen dxva2" FF_LIBRARY_EXTENSION " failed", "dxva2" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(dxva2, "dlopen dxva2" FF_LIBRARY_EXTENSION " failed", "dxva2" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxva2, GetPhysicalMonitorsFromHMONITOR)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(dxva2, GetMonitorBrightness)
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBtrfsDiskUsage
|
||||
{
|
||||
uint64_t total;
|
||||
uint64_t used;
|
||||
const char* type;
|
||||
bool dup;
|
||||
} FFBtrfsDiskUsage;
|
||||
|
||||
typedef struct FFBtrfsResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf uuid;
|
||||
FFstrbuf devices;
|
||||
FFstrbuf features;
|
||||
uint32_t generation;
|
||||
uint32_t nodeSize;
|
||||
uint32_t sectorSize;
|
||||
uint64_t totalSize;
|
||||
uint64_t globalReservationUsed;
|
||||
uint64_t globalReservationTotal;
|
||||
FFBtrfsDiskUsage allocation[3];
|
||||
} FFBtrfsResult;
|
||||
|
||||
const char* ffDetectBtrfs(FFlist* result /* list of FFBtrfsResult */);
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "btrfs.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include <fcntl.h>
|
||||
|
||||
enum { uuidLen = (uint32_t) __builtin_strlen("00000000-0000-0000-0000-000000000000") };
|
||||
|
||||
static const char* enumerateDevices(FFBtrfsResult* item, int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
int subfd = openat(dfd, "devices", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/devices\") == -1";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd);
|
||||
if(dirp == NULL)
|
||||
return "fdopendir(\"/sys/fs/btrfs/UUID/devices\") == NULL";
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
if (item->devices.length)
|
||||
ffStrbufAppendC(&item->devices, ',');
|
||||
ffStrbufAppendS(&item->devices, entry->d_name);
|
||||
|
||||
char path[sizeof(entry->d_name) + sizeof("/size") + 1];
|
||||
snprintf(path, ARRAY_SIZE(path), "%s/size", entry->d_name);
|
||||
|
||||
if (ffReadFileBufferRelative(subfd, path, buffer))
|
||||
item->totalSize += ffStrbufToUInt(buffer, 0) * 512;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* enumerateFeatures(FFBtrfsResult* item, int dfd)
|
||||
{
|
||||
int subfd = openat(dfd, "features", O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/features\") == -1";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd);
|
||||
if(dirp == NULL)
|
||||
return "fdopendir(\"/sys/fs/btrfs/UUID/features\") == NULL";
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
if (item->features.length)
|
||||
ffStrbufAppendC(&item->features, ',');
|
||||
ffStrbufAppendS(&item->features, entry->d_name);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int subfd = openat(dfd, "allocation", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
|
||||
if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/allocation\") == -1";
|
||||
|
||||
if (ffReadFileBufferRelative(subfd, "global_rsv_size", buffer))
|
||||
item->globalReservationTotal = ffStrbufToUInt(buffer, 0);
|
||||
else
|
||||
return "ffReadFileBuffer(\"/sys/fs/btrfs/UUID/allocation/global_rsv_size\") == NULL";
|
||||
|
||||
if (ffReadFileBufferRelative(subfd, "global_rsv_reserved", buffer))
|
||||
item->globalReservationUsed = ffStrbufToUInt(buffer, 0);
|
||||
item->globalReservationUsed = item->globalReservationTotal - item->globalReservationUsed;
|
||||
|
||||
#define FF_BTRFS_DETECT_TYPE(index, _type) \
|
||||
if (ffReadFileBufferRelative(subfd, #_type "/total_bytes", buffer)) \
|
||||
item->allocation[index].total = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
if (ffReadFileBufferRelative(subfd, #_type "/bytes_used", buffer)) \
|
||||
item->allocation[index].used = ffStrbufToUInt(buffer, 0); \
|
||||
\
|
||||
item->allocation[index].dup = faccessat(subfd, #_type "/dup/", F_OK, 0) == 0; \
|
||||
\
|
||||
item->allocation[index].type = #_type;
|
||||
|
||||
FF_BTRFS_DETECT_TYPE(0, data);
|
||||
FF_BTRFS_DETECT_TYPE(1, metadata);
|
||||
FF_BTRFS_DETECT_TYPE(2, system);
|
||||
|
||||
#undef FF_BTRFS_DETECT_TYPE
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectBtrfs(FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/fs/btrfs/");
|
||||
if(dirp == NULL)
|
||||
return "opendir(\"/sys/fs/btrfs\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.')
|
||||
continue;
|
||||
if (strlen(entry->d_name) != uuidLen)
|
||||
continue;
|
||||
|
||||
FFBtrfsResult* item = ffListAdd(result);
|
||||
(*item) = (FFBtrfsResult){
|
||||
.uuid = ffStrbufCreateNS(uuidLen, entry->d_name),
|
||||
.name = ffStrbufCreate(),
|
||||
.devices = ffStrbufCreate(),
|
||||
.features = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY);
|
||||
if (dfd < 0) continue;
|
||||
|
||||
if (ffAppendFileBufferRelative(dfd, "label", &item->name))
|
||||
ffStrbufTrimRightSpace(&item->name);
|
||||
|
||||
enumerateDevices(item, dfd, &buffer);
|
||||
|
||||
enumerateFeatures(item, dfd);
|
||||
|
||||
if (ffReadFileBufferRelative(dfd, "generation", &buffer))
|
||||
item->generation = (uint32_t) ffStrbufToUInt(&buffer, 0);
|
||||
|
||||
if (ffReadFileBufferRelative(dfd, "nodesize", &buffer))
|
||||
item->nodeSize = (uint32_t) ffStrbufToUInt(&buffer, 0);
|
||||
|
||||
if (ffReadFileBufferRelative(dfd, "sectorsize", &buffer))
|
||||
item->sectorSize = (uint32_t) ffStrbufToUInt(&buffer, 0);
|
||||
|
||||
detectAllocation(item, dfd, &buffer);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "btrfs.h"
|
||||
|
||||
const char* ffDetectBtrfs(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -16,7 +16,7 @@ const char* ffDetectCamera(FFlist* result)
|
||||
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
path[sizeof(path) - 2] = (char) (i + '0');
|
||||
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
@@ -43,10 +43,10 @@ const char* ffDetectCamera(FFlist* result)
|
||||
case V4L2_COLORSPACE_JPEG: ffStrbufInitStatic(&camera->colorspace, "JPEG"); break;
|
||||
case V4L2_COLORSPACE_REC709:
|
||||
case V4L2_COLORSPACE_SRGB: ffStrbufInitStatic(&camera->colorspace, "sRGB"); break;
|
||||
case V4L2_COLORSPACE_OPRGB: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
|
||||
case V4L2_COLORSPACE_BT2020: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case V4L2_COLORSPACE_RAW: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
|
||||
case V4L2_COLORSPACE_DCI_P3: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
case 9 /* V4L2_COLORSPACE_OPRGB */: ffStrbufInitStatic(&camera->colorspace, "Adobe RGB"); break;
|
||||
case 10 /* V4L2_COLORSPACE_BT2020 */: ffStrbufInitStatic(&camera->colorspace, "BT.2020"); break;
|
||||
case 11 /* V4L2_COLORSPACE_RAW */: ffStrbufInitStatic(&camera->colorspace, "RAW"); break;
|
||||
case 12 /* V4L2_COLORSPACE_DCI_P3 */: ffStrbufInitStatic(&camera->colorspace, "DCI-P3"); break;
|
||||
default: ffStrbufInit(&camera->colorspace); break;
|
||||
}
|
||||
camera->width = fmt.fmt.pix.width;
|
||||
|
||||
@@ -21,9 +21,9 @@ private:
|
||||
extern "C"
|
||||
const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(mfplat, NULL, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(mfplat, "dlopen mfplat" FF_LIBRARY_EXTENSION " failed", "mfplat" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mfplat, MFCreateAttributes)
|
||||
FF_LIBRARY_LOAD(mf, NULL, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD(mf, "dlopen mf" FF_LIBRARY_EXTENSION " failed", "mf" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(mf, MFEnumDeviceSources)
|
||||
|
||||
const char* error = ffInitCom();
|
||||
@@ -52,7 +52,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
|
||||
wchar_t buffer[256];
|
||||
uint32_t length = 0;
|
||||
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0)
|
||||
if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, ARRAY_SIZE(buffer), &length)) || length == 0)
|
||||
continue;
|
||||
|
||||
FFCameraResult* camera = (FFCameraResult*) ffListAdd(result);
|
||||
@@ -63,7 +63,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result)
|
||||
camera->width = 0;
|
||||
camera->height = 0;
|
||||
|
||||
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0)
|
||||
if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, ARRAY_SIZE(buffer), &length)) && length > 0)
|
||||
ffStrbufSetNWS(&camera->id, length, buffer);
|
||||
|
||||
IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "chassis.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
const char* ffDetectChassis(FFChassisResult* chassis)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.dmi.chassis-type", &chassis->type) == NULL)
|
||||
ffCleanUpSmbiosValue(&chassis->type);
|
||||
if (ffSysctlGetString("machdep.dmi.chassis-version", &chassis->version) == NULL)
|
||||
ffCleanUpSmbiosValue(&chassis->version);
|
||||
if (ffSysctlGetString("machdep.dmi.chassis-vendor", &chassis->vendor) == NULL)
|
||||
ffCleanUpSmbiosValue(&chassis->vendor);
|
||||
if (ffSysctlGetString("machdep.dmi.chassis-serial", &chassis->serial) == NULL)
|
||||
ffCleanUpSmbiosValue(&chassis->serial);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user