mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
814 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 02aafbd7f4 | |||
| 72da8150bd | |||
| aca2b5336d | |||
| c79b67efc1 | |||
| 30af91ce8e | |||
| 6c56348e54 | |||
| 531b25dc2f | |||
| 8c6dc34654 | |||
| cf2034b93e | |||
| f7db03b8c4 | |||
| 8647e366f9 | |||
| 1bf41d68f9 | |||
| 1ac1f1f889 | |||
| 14f1278485 | |||
| c2c6856159 | |||
| c89f3d2896 | |||
| 8e773470df | |||
| ea4fc7bdda | |||
| 468d1e0903 | |||
| 6851e7b082 | |||
| a734f18fd5 | |||
| 30b1e29785 | |||
| dde0c22195 | |||
| 1311a809db | |||
| 60a54f4880 | |||
| b4e65e7e48 | |||
| 6f3ed4a7b4 | |||
| cc8f8ff0f7 | |||
| 8a00f2d901 | |||
| c5c0e543e4 | |||
| 97255f37da | |||
| fb8a04f97a | |||
| c3ce5ac947 | |||
| eae69049b2 | |||
| 102e8fcc72 | |||
| 8372708f98 | |||
| 5011edc9d9 | |||
| 94a5228ffc | |||
| 382c0cd7c3 | |||
| ab496b23b7 | |||
| 939f428da7 | |||
| 2d496c91e1 | |||
| 442d58b646 | |||
| 4d377b94b7 | |||
| 7248868e33 | |||
| 2eda6464ad | |||
| 2622fc12a6 | |||
| b178e43428 | |||
| d00fca26c5 | |||
| 23e4d1c4aa | |||
| 6871c8bb73 | |||
| 61adc7cf64 | |||
| 9ba30adcba | |||
| 010b2c6262 | |||
| c65fb1a868 | |||
| 2029679ea5 | |||
| 817f70c2cd | |||
| 3a1f0485f4 | |||
| 64910d0781 | |||
| 821462e152 | |||
| b015fd579c | |||
| 8b40a81e22 | |||
| 8be64714ba | |||
| fe5d739cba | |||
| dba0672a11 | |||
| 3ed6acf3ca | |||
| 8c74c54bb0 | |||
| 818473102c | |||
| f1cc4a7805 | |||
| c574af97a4 | |||
| 74ae84e719 | |||
| 98738b6920 | |||
| 2e5769def2 | |||
| 18a6929662 | |||
| 0e61d1134d | |||
| 4abb183735 | |||
| d5b56be4ff | |||
| 1854953d8c | |||
| 2406015c81 | |||
| ec7f14ab96 | |||
| d94cdf4424 | |||
| 40e57b7698 | |||
| 974c658fff | |||
| ad0ddfd7f1 | |||
| 1da8367f55 | |||
| bdbc885811 | |||
| 86e5a5997b | |||
| 9832a0e45b | |||
| addf674621 | |||
| 863c5583ef | |||
| 45cbc6de83 | |||
| e68f766b4d | |||
| 29d7a1acac | |||
| 8d59d14b80 | |||
| ed1883909a | |||
| 049701a8a9 | |||
| 13b7bc89eb | |||
| 92fe44183d | |||
| 8ebc980c17 | |||
| dbeb338bda | |||
| 65ff11a8d0 | |||
| 7a73211484 | |||
| ca049997b1 | |||
| a9f021ccb9 | |||
| 55249c2294 | |||
| c13da56959 | |||
| 665c7cd5d3 | |||
| 469e21cce9 | |||
| 925e09c88a | |||
| 488454c1aa | |||
| c67c52d606 | |||
| e4e11ee509 | |||
| a3e2592555 | |||
| e0e966dadf | |||
| b079a8643b | |||
| 3291a9945f | |||
| 68fd21d0e4 | |||
| 0e1ef96992 | |||
| c377872438 | |||
| 4f42d38e4d | |||
| 7b2243496b | |||
| 960a817d03 | |||
| 6917f9479e | |||
| 8559cc45eb | |||
| 40e33c676d | |||
| d20371040e | |||
| 71faf1c7e3 | |||
| d182f3f743 | |||
| 39e009b945 | |||
| a1873f3e9e | |||
| 636bcaaaf9 | |||
| 3fcbd80ef0 | |||
| 38887e7fbd | |||
| da958e11f9 | |||
| c2ed71c4eb | |||
| 2e1ddcf9f8 | |||
| f1cc2d124c | |||
| 1e32a95f83 | |||
| 9e959bc57f | |||
| e68406ee22 | |||
| ba69e316b2 | |||
| f3e8e8af52 | |||
| c9adab3892 | |||
| c8d1d29017 | |||
| 541acca7c0 | |||
| ddf5099461 | |||
| 781a692b06 | |||
| 9c37f1b370 | |||
| a66c26f4df | |||
| 3bd750bedf | |||
| 4a1ada604c | |||
| e5f57a34a2 | |||
| 20a3737dce | |||
| e0452d9db5 | |||
| d8e74ba84c | |||
| 04b13096ac | |||
| 64d4035cae | |||
| 5e0ba57f53 | |||
| d89263c218 | |||
| 6a42588786 | |||
| 5883bf359c | |||
| 6a6b4070ca | |||
| 2c80cd6d29 | |||
| fa4b00b027 | |||
| 5fdc924b5d | |||
| 3d4a117093 | |||
| 7ec0c664c5 | |||
| 9d2df589b5 | |||
| 7107d08e92 | |||
| 4c34f99c12 | |||
| d7a8c92b46 | |||
| bbb29ff766 | |||
| 35235b9557 | |||
| 6b94605804 | |||
| 4b2fa07fdc | |||
| e203f4eeaf | |||
| 8db70b40e2 | |||
| 1f967849e5 | |||
| d60b2ddfd4 | |||
| fb68d8a841 | |||
| 047411ba87 | |||
| 08ed14b42a | |||
| d94a41cc1b | |||
| 81b7fb06c1 | |||
| c8debccd16 | |||
| 2853bd15c0 | |||
| 2f4146fde8 | |||
| eeceade14e | |||
| 1875c78e96 | |||
| f389864e17 | |||
| b9317734b9 | |||
| 4df4a1de78 | |||
| 0cd8c6ead6 | |||
| f8479dae94 | |||
| a7d623fa75 | |||
| 7a8ffb27bd | |||
| 73c0347469 | |||
| fde5f3bd0f | |||
| 9e1b1302fb | |||
| 7e235b6be0 | |||
| f43e1fd614 | |||
| c7b061eebd | |||
| a0f579072f | |||
| d439ce8eb5 | |||
| e2a714732a | |||
| a993a6f126 | |||
| 8eb8f710d0 | |||
| 526868e355 | |||
| 768238cb46 | |||
| 2d938042d0 | |||
| 9a54d92e9f | |||
| 839abab744 | |||
| c054570308 | |||
| ed69a7059b | |||
| 6b92659512 | |||
| 7e04305d1c | |||
| 87e13543da | |||
| 7a2cbc060f | |||
| f22d73d473 | |||
| e629126d73 | |||
| 9ac635e2e6 | |||
| 1b1b0521f4 | |||
| 41d0f61ee0 | |||
| 9de5d9008b | |||
| 576a9cc6fe | |||
| bd61d08afe | |||
| 4672b78481 | |||
| 36b0fdbcda | |||
| 7626ef6eaa | |||
| 115108b3f1 | |||
| 154f9f462b | |||
| a96a9fc31d | |||
| 23b43244c5 | |||
| 9dfb404a0d | |||
| ff3028c656 | |||
| 2f706ed494 | |||
| 06427ee62b | |||
| fe66eb3df0 | |||
| 6e1ab12399 | |||
| 484e05eae3 | |||
| 5d3fb98072 | |||
| 0c30590088 | |||
| 20cd4ce125 | |||
| 1c7aa89228 | |||
| f270255770 | |||
| 4b62a3c75b | |||
| 1557f0c556 | |||
| ef7f61309f | |||
| f59491b25d | |||
| e3592eb2c3 | |||
| 305776eb94 | |||
| 599e0d393d | |||
| 561574ae94 | |||
| 3dd78422eb | |||
| 5c546ab8e7 | |||
| 3e9274040d | |||
| 630d876e2d | |||
| 1938be86ff | |||
| 0980d5f0ad | |||
| d8c1b3b61b | |||
| 969523ae8a | |||
| 5d960ec744 | |||
| 3b36b8ca57 | |||
| 05f14764e6 | |||
| 3a180b24e3 | |||
| 02ab58e001 | |||
| fd158b41e1 | |||
| 89e0ede12f | |||
| 4d7b2410ef | |||
| c1f6a2f755 | |||
| 9c455c3b0f | |||
| d4ea9dfd21 | |||
| 08071e6e7e | |||
| ec87174f30 | |||
| 835e5b51c9 | |||
| 07c5ef255e | |||
| 476b55c17d | |||
| 4a53cfa312 | |||
| 50ea515476 | |||
| cbd9f72bc8 | |||
| 29eaa35f4c | |||
| 97c89c39d3 | |||
| 5769791185 | |||
| 894c66d793 | |||
| 75290154b0 | |||
| b08eea76b1 | |||
| 61d83af9ea | |||
| 2d497038eb | |||
| f8a5d5561a | |||
| 2e7e68ef23 | |||
| b812f3ccde | |||
| 6da8181bbe | |||
| a51dd641c1 | |||
| 0d20164d40 | |||
| 3320532668 | |||
| bcc6492115 | |||
| c60bc8ee5b | |||
| 4eefab8ccf | |||
| 9cda7e20fb | |||
| 79d0197dcf | |||
| ba01b1e4ce | |||
| 58908f69ba | |||
| 114088b845 | |||
| 6e77b592cb | |||
| 73bc71e922 | |||
| 090529ffef | |||
| 3c291f1af9 | |||
| fc31fe4aa4 | |||
| 563f9598be | |||
| 03bc2dade9 | |||
| 09d683b706 | |||
| 523a9590b8 | |||
| 3c3188eb05 | |||
| 354062118f | |||
| 85d7390fa8 | |||
| 8509f97054 | |||
| 8d5d8b4c90 | |||
| 536ad9594e | |||
| a57bbbadf4 | |||
| 3def466ee0 | |||
| 59868c66a0 | |||
| e13eb05073 | |||
| cdda65e6ad | |||
| a7ac89818c | |||
| 06956d2cf4 | |||
| ac52ea1afb | |||
| b68e0ce8ae | |||
| 8d6ed2e847 | |||
| 4211d15cdb | |||
| 2ff8d8864d | |||
| 884c902d93 | |||
| 16c56254b0 | |||
| 88eaab670f | |||
| 3e7630e074 | |||
| 744455d8b7 | |||
| bcc8f6d0b8 | |||
| 90ca6ee3cd | |||
| b679185c87 | |||
| 6bbed12083 | |||
| f04851891e | |||
| f94d9ca3bd | |||
| f833dda3b9 | |||
| ceecb39bc5 | |||
| c957ca7230 | |||
| 5dfd2676c2 | |||
| d650f67ece | |||
| 760e82913a | |||
| e64a44a3e6 | |||
| be9cf00b05 | |||
| 52fdabeb2e | |||
| 846f4c003e | |||
| dc5f2ac577 | |||
| 663650cb61 | |||
| 45aecae221 | |||
| 3d3669ae3a | |||
| ac2aba0faf | |||
| d0ca944b9c | |||
| 3d7c631abd | |||
| abe78823b6 | |||
| 7e03b03cb7 | |||
| 27fe997dc3 | |||
| fe46159e40 | |||
| 031aa985f1 | |||
| 07c61f70d9 | |||
| 71b05d2594 | |||
| 98665d1b82 | |||
| da0eedf888 | |||
| 1133cb619b | |||
| a091d209cf | |||
| 47c658815b | |||
| b0d0c74073 | |||
| 9535b4d480 | |||
| c64cbf57d8 | |||
| d11235bbe2 | |||
| 3054c6618e | |||
| f34d51dddc | |||
| e05ac797cc | |||
| 187059deef | |||
| 5c9f184314 | |||
| 49725c2cc6 | |||
| eec9a26952 | |||
| 88d616e978 | |||
| 4fccad5d10 | |||
| ec18363f51 | |||
| b87a36785b | |||
| 1d7b212d8d | |||
| 4b6f2a9efa | |||
| bdaf303da4 | |||
| 3fb773eedd | |||
| e73647973d | |||
| d2b3a075b2 | |||
| f139148745 | |||
| e2ec2c695c | |||
| ba4ec47a8c | |||
| de5ef3842c | |||
| 1129ed9be4 | |||
| 0d4f1544c7 | |||
| e68a9476b5 | |||
| 17556c7a95 | |||
| eca9f626a5 | |||
| 7562e05123 | |||
| bf17f2b4b9 | |||
| 88e193e9fd | |||
| e474a47fad | |||
| c77fb71a69 | |||
| 48dd5976e1 | |||
| 093f7e438b | |||
| 0a0c1745b3 | |||
| 7b5dc58140 | |||
| 8681d2f74a | |||
| 2b20ed873c | |||
| ae3c15b7fd | |||
| 8dafd8f300 | |||
| c9a1765f29 | |||
| cc246ea239 | |||
| 0ae5fceb07 | |||
| 6dd18050be | |||
| 9eca6e0b48 | |||
| 4d58d1be66 | |||
| 6694388969 | |||
| f7058cd125 | |||
| 80033b656f | |||
| 1c719fa743 | |||
| a9f5722fd9 | |||
| 0952d7917f | |||
| a3f50f32bf | |||
| ab1bfffbd4 | |||
| 41d6187f11 | |||
| d4b175b146 | |||
| 8905962389 | |||
| d9d34ccbbb | |||
| d21048c165 | |||
| 8b0c32a35f | |||
| db269d29e8 | |||
| f9f628eae6 | |||
| 92e9fbf2eb | |||
| db6e4f4bfc | |||
| b662db452f | |||
| 0d2ccb5fe5 | |||
| d33b5d60b6 | |||
| ef5d12395b | |||
| e18c261054 | |||
| 8851821484 | |||
| 3489cc8fe8 | |||
| 28bc97b92b | |||
| dbc5a7961e | |||
| 5f43f63990 | |||
| b775fe7486 | |||
| 60eaa326a2 | |||
| 672d4ad543 | |||
| 96e9e61437 | |||
| dbc6f70f19 | |||
| dfc9bc265c | |||
| 2ce511c4d3 | |||
| 99415a3841 | |||
| 244625d26a | |||
| 840434e709 | |||
| 72afa9ef99 | |||
| 7400f14322 | |||
| 85654316c7 | |||
| 8ecd58dd14 | |||
| 65c7f68c31 | |||
| bf6d0f871a | |||
| 3cd7c6c916 | |||
| 3227e934de | |||
| b66a009046 | |||
| 6ef4f62d5b | |||
| c038024108 | |||
| df49a01827 | |||
| 924c670915 | |||
| be89dff12a | |||
| c1807a1108 | |||
| b569acbb5d | |||
| 6e571a3163 | |||
| 01e78e2179 | |||
| 1b219a9d5c | |||
| 0ac01003b2 | |||
| a36bdfabd0 | |||
| 570abb194a | |||
| 4e00f37be9 | |||
| 334afc9838 | |||
| 64f9e53a36 | |||
| b94c6ab8d5 | |||
| 38ea333644 | |||
| efbdaf7aaf | |||
| aee7b37fc8 | |||
| 664460cd34 | |||
| a66e1b2e6d | |||
| 8000574a82 | |||
| 2eae5a86d2 | |||
| 75da934815 | |||
| ac71ebcad9 | |||
| 383a6c8a05 | |||
| 8e79fde0d9 | |||
| 4f4622eab9 | |||
| a2327b7350 | |||
| b76ada7f30 | |||
| 59b568a6d0 | |||
| 3d6bd26e59 | |||
| 4e17688b7c | |||
| f34548621f | |||
| 7a2e071081 | |||
| de7b57d807 | |||
| 6de9d0c024 | |||
| 8f69533f30 | |||
| d463853aeb | |||
| 1047d1cf6e | |||
| 0bfa12c38c | |||
| c8e4962cfd | |||
| 171005b6a3 | |||
| 8526f4a021 | |||
| 3e5d129248 | |||
| 6e98db3bf3 | |||
| ff0236639a | |||
| 959bf769fb | |||
| 3ae7c4f788 | |||
| 143b3df771 | |||
| c0c59a890a | |||
| 3c5f69b874 | |||
| 36a452c852 | |||
| c66b32fc6f | |||
| bc129a65d9 | |||
| 1137e8d1c9 | |||
| 95a44d3a33 | |||
| b8b2fab499 | |||
| 7aceb1072a | |||
| 13723893ba | |||
| 6fd4720faf | |||
| 966b8452b7 | |||
| 8dc4f77f42 | |||
| ab0240e9b7 | |||
| 399f262692 | |||
| d1385804bb | |||
| 948a965c7a | |||
| a13935e232 | |||
| 46f920ae2a | |||
| e79b561f2a | |||
| 9018fda92e | |||
| 76b8b9a44b | |||
| 36a129f668 | |||
| 24e94acbb9 | |||
| 716f0a3bbb | |||
| f839fcfa29 | |||
| 41d930b1e1 | |||
| 5e615d12d5 | |||
| 17711ee5c8 | |||
| 9ff3142b61 | |||
| 8e5c2adda3 | |||
| 01d37653b0 | |||
| f5dbbb70ef | |||
| fc3f47742a | |||
| 1d2b6c0b1a | |||
| 5ebf984e9a | |||
| bfa59d2c04 | |||
| c1c59cff6d | |||
| 519dae9462 | |||
| 34419d9bcf | |||
| 532b3cd457 | |||
| 437006f5f1 | |||
| 1c858ae835 | |||
| 349fdd47e4 | |||
| c64854804d | |||
| f3e54f33c2 | |||
| 5f3ff07b4b | |||
| e8db71fe19 | |||
| 8984aa740e | |||
| c081268b7c | |||
| fae8d1dd10 | |||
| 217ea61568 | |||
| ba7885913d | |||
| a8afd05d19 | |||
| f4f1592bfa | |||
| cdc8124883 | |||
| c53191a441 | |||
| 14aadd5b61 | |||
| e38f094c16 | |||
| 452d52c217 | |||
| c585e09ef0 | |||
| 464e00d616 | |||
| b8e25bdc4e | |||
| 379c39d8b5 | |||
| f2a41b82bc | |||
| d1a98fe69f | |||
| ef3412f81b | |||
| 1812c30fbf | |||
| 3c45f2e590 | |||
| 735a464f68 | |||
| 3e3dfb4a02 | |||
| f77a9c185d | |||
| d3a5f986a8 | |||
| ef60910e51 | |||
| 565934ba2e | |||
| 5c5e12f0a7 | |||
| b3e7451a08 | |||
| da76dcb2fe | |||
| cbc8b1f11d | |||
| 5ca4268be2 | |||
| ff8bfadd25 | |||
| 1fc0f75776 | |||
| bf707c2e94 | |||
| 08cd4ac1ee | |||
| 48fc598ccb | |||
| 3a8138e3da | |||
| 4251456619 | |||
| 5bc6d16138 | |||
| 11374e73ae | |||
| 373cb4106a | |||
| a0949c5675 | |||
| 97b1eb155f | |||
| 093cc6fba2 | |||
| c8a3ae9186 | |||
| 778013aec9 | |||
| e6af1bfb91 | |||
| 9d8a83349c | |||
| 3bc6be9139 | |||
| 1eef6f837b | |||
| 85ed4b136f | |||
| 339e08fef1 | |||
| 5957831f3f | |||
| 016b1e6961 | |||
| 486ade0e71 | |||
| e021cfe77a | |||
| a016397961 | |||
| 99e8d1f2bb | |||
| 263d2902dd | |||
| 292fa0686f | |||
| f2755a844b | |||
| 1d21d02878 | |||
| b3062499f4 | |||
| 49bb957c86 | |||
| 8f27e43929 | |||
| 8774fb3fb7 | |||
| 356501270a | |||
| 5a04a2ecc3 | |||
| edcd7995e5 | |||
| 7f212025de | |||
| 63cc8e5523 | |||
| c3023259e2 | |||
| 994a8b4dd0 | |||
| 76710c8159 | |||
| 70820e424b | |||
| 9221e2b41d | |||
| 71a2e55869 | |||
| dc5ff01e74 | |||
| fc8ddce182 | |||
| dd67010e5c | |||
| d1ba690973 | |||
| 01f400c15f | |||
| 33c905aa99 | |||
| fe7c4f724e | |||
| abadcb95bd | |||
| 3d8050fd5c | |||
| 4d842ac6b6 | |||
| b76e62685e | |||
| 1279bbcf28 | |||
| 4e9fecc767 | |||
| 1c4953a467 | |||
| 3ad5d5c8b0 | |||
| 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 |
+2
-2
@@ -1,5 +1,5 @@
|
||||
[codespell]
|
||||
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,slave,sur,doas,conexant,ags
|
||||
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h
|
||||
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu
|
||||
|
||||
@@ -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
|
||||
+422
-118
@@ -35,7 +35,7 @@ jobs:
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -56,11 +56,11 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -73,13 +73,19 @@ jobs:
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev python3-requests
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -87,7 +93,7 @@ jobs:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -111,7 +117,7 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
@@ -125,7 +131,7 @@ jobs:
|
||||
|
||||
linux-aarch64:
|
||||
name: Linux-aarch64
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-22.04-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -133,24 +139,50 @@ jobs:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
id: runcmd
|
||||
with:
|
||||
arch: aarch64
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: cat /etc/os-release
|
||||
run: cat /etc/os-release
|
||||
|
||||
- name: cat /proc/cpuinfo
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: configure project
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: get fastfetch version
|
||||
id: ffversion
|
||||
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -158,9 +190,9 @@ jobs:
|
||||
name: fastfetch-linux-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-armv7:
|
||||
name: Linux-armv7
|
||||
runs-on: ubuntu-22.04
|
||||
linux-armv7l:
|
||||
name: Linux-armv7l
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -169,7 +201,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: armv7
|
||||
@@ -181,7 +213,7 @@ jobs:
|
||||
# CMake installed by apt has bug `list sub-command REMOVE_ITEM requires two or more arguments`
|
||||
wget --no-check-certificate https://apt.kitware.com/ubuntu/pool/main/c/cmake/{cmake_3.29.2-0kitware1ubuntu20.04.1_armhf.deb,cmake-data_3.29.2-0kitware1ubuntu20.04.1_all.deb}
|
||||
dpkg -i *.deb
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get install -y make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
@@ -189,17 +221,17 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv7
|
||||
name: fastfetch-linux-armv7l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-22.04
|
||||
linux-armv6l:
|
||||
name: Linux-armv6l
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -208,15 +240,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v2
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
distro: ubuntu22.04
|
||||
arch: armv6
|
||||
distro: bookworm
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
apt-get update && apt-get install -y 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 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
|
||||
@@ -224,7 +257,42 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-armv6l
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-riscv64:
|
||||
name: Linux-riscv64
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
distro: ubuntu22.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libddcutil-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -232,6 +300,76 @@ jobs:
|
||||
name: fastfetch-linux-riscv64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-ppc64le:
|
||||
name: Linux-ppc64le
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: 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 ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-ppc64le
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
linux-s390x:
|
||||
name: Linux-s390x
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: uraimo/run-on-arch-action@v3
|
||||
id: runcmd
|
||||
with:
|
||||
arch: s390x
|
||||
distro: ubuntu20.04
|
||||
githubToken: ${{ github.token }}
|
||||
run: |
|
||||
uname -a
|
||||
apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-linux-s390x
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
musl-amd64:
|
||||
name: Musl-amd64
|
||||
runs-on: ubuntu-latest
|
||||
@@ -240,19 +378,17 @@ jobs:
|
||||
|
||||
- name: setup alpine linux
|
||||
uses: jirutka/setup-alpine@master
|
||||
with:
|
||||
branch: v3.19
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev py3-requests gcc g++
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -GNinja .
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -GNinja .
|
||||
cmake --build . --target package --verbose -j4
|
||||
shell: alpine.sh {0}
|
||||
|
||||
@@ -263,7 +399,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
shell: alpine.sh {0}
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -272,9 +408,9 @@ jobs:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-latest
|
||||
macos-amd64:
|
||||
name: macOS-amd64
|
||||
runs-on: macos-13
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -289,20 +425,12 @@ jobs:
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: c
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: perform CodeQL analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
@@ -319,12 +447,59 @@ jobs:
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-universal
|
||||
name: fastfetch-macos-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-aarch64:
|
||||
name: macOS-aarch64
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
@@ -351,7 +526,7 @@ jobs:
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
cpack
|
||||
|
||||
- name: upload artifacts
|
||||
@@ -377,19 +552,19 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '14.1'
|
||||
version: '14.3'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg update
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py311-requests chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On .
|
||||
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -397,41 +572,6 @@ 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
|
||||
@@ -449,18 +589,18 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.5'
|
||||
version: '7.7'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio hwdata py3-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -485,18 +625,18 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '10.0'
|
||||
version: '10.1'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick pulseaudio opencl-headers ocl-icd py312-requests
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=ON .
|
||||
sudo pkgin -y install cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick opencl-headers ocl-icd
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -504,6 +644,106 @@ jobs:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
dragonfly-amd64:
|
||||
name: DragonFly-amd64
|
||||
runs-on: ubuntu-latest
|
||||
if: false
|
||||
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 opencl ocl-icd v4l_compat chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
haiku-amd64:
|
||||
name: Haiku-amd64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Fixup VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
sync_files: false
|
||||
shutdown_vm: false
|
||||
run: |
|
||||
mv '/home/runner/work' '/boot/home/work'
|
||||
ln -sf '/boot/home/work' '/home/runner/work'
|
||||
|
||||
- name: Sync files to VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
sync_files: runner-to-vm
|
||||
shutdown_vm: false
|
||||
run: |
|
||||
chown -R $(id -u):$(id -g) $(pwd)
|
||||
ls -l
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
version: 'r1beta5'
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
sync_files: vm-to-runner
|
||||
run: |
|
||||
uname -a
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
@@ -536,8 +776,67 @@ jobs:
|
||||
- name: copy necessary dlls
|
||||
run: cp /clang64/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_x64.dll
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
|
||||
windows-aarch64:
|
||||
name: Windows-aarch64
|
||||
runs-on: windows-11-arm
|
||||
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: CLANGARM64
|
||||
update: true
|
||||
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
@@ -555,19 +854,19 @@ jobs:
|
||||
run: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-amd64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
name: fastfetch-windows-aarch64
|
||||
path: ./fastfetch-windows-aarch64.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
@@ -576,16 +875,21 @@ jobs:
|
||||
needs:
|
||||
- linux-amd64
|
||||
- linux-aarch64
|
||||
- linux-armv7
|
||||
- linux-armv7l
|
||||
- linux-armv6l
|
||||
- linux-riscv64
|
||||
- linux-ppc64le
|
||||
- linux-s390x
|
||||
- musl-amd64
|
||||
- macos-universal
|
||||
- macos-amd64
|
||||
- macos-aarch64
|
||||
- freebsd-amd64
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
- dragonfly-amd64
|
||||
- sunos-amd64
|
||||
- haiku-amd64
|
||||
- windows-amd64
|
||||
- windows-aarch64
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
+564
-2
@@ -1,3 +1,565 @@
|
||||
# 2.48.1
|
||||
|
||||
Features:
|
||||
* Add support for detecting Openbox WM version (WM, Linux)
|
||||
* Improve reliability of child process spawning on Windows (Windows)
|
||||
* Add a new option `--packages-combined`, which combines related package managers into single counts (#1851, Packages)
|
||||
* For example: if you have both `flatpak-system` and `flatpak-user` packages installed, they will be combined into a single `flatpak` count with `--packages-combined` enabled.
|
||||
* Add `modules[n].condition` to conditionally enable modules on different platforms
|
||||
* Useful when sharing configuration files across platforms
|
||||
* For example:
|
||||
```jsonc
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "This string will be printed on Intel macOS only",
|
||||
"condition": {
|
||||
"system": "macOS", // Can be an array, optional
|
||||
"arch": "x86_64" // Can be an array, optional too
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Revert the change of `posix_spawn` in v2.48.0 for Android and OpenBSD (Android / OpenBSD)
|
||||
* Fix completion for Android 7 (Required by Termux)
|
||||
|
||||
# 2.48.0
|
||||
|
||||
Features:
|
||||
* Add support for detecting Fedora variants (#1830, OS, Linux)
|
||||
* Currently supported variants: CoreOS, Kinoite, Sericea, Silverblue
|
||||
* Optimize GPU detection on Windows when `--gpu-driver-specific` is not used (GPU, Windows)
|
||||
* Improve accuracy of GPU type detection. Previously it was guessed based on the dedicated vmem size, which causes issues on newer AMD integrated GPUs such as 9000 HX and AI 9 HX series. Supported on Windows 8.1 or later.
|
||||
* Add support for generic frequency detection of GPU 3D engine on Windows 11 22H2 or later.
|
||||
* Improve performance. GPU temperature detection is significantly improved when `--gpu-driver-specific` is not used.
|
||||
* Improve performance and security when spawning child processes by replacing `fork-exec` with `posix_spawn` (*nix)
|
||||
* Improve accuracy of sound device detection on macOS (Sound, macOS)
|
||||
* Trim leading and trailing whitespaces in disk serial numbers (PhysicalDisk)
|
||||
* Add `/etc/profiles/per-user` detection for Nix user packages (#1782, Packages, Linux)
|
||||
* Introduce `years` (whole years as integer), `days-of-year` (days since the last anniversary) and `years-fraction` (years as fraction, e.g. 1.5 means 1 year and 6 months) formatting placeholder to `Disk` (since disk creation), `Users` (since user login) and `Uptime` (since system boot) modules
|
||||
* For example: `fastfetch -s disk --disk-key 'OS Installation' --disk-format '{years} years {days-of-year} days'`
|
||||
* Add `--fraction-ndigits` option to specify the number of digits after the decimal point when displaying ordinary fractional values
|
||||
* Typically used with `{years-fraction}` above
|
||||
* This option does not affect percentage values, sizes, etc, which are controlled by individual options.
|
||||
|
||||
Bugfixes:
|
||||
* Fix compilation issues when not using `-DBINARY_LINK_TYPE=dlopen`
|
||||
* Regression from v2.47.0
|
||||
* Note: this option was added for debugging purposes only and is not recommended for production use
|
||||
* Replace `MTLDevice::hasUnifiedMemory` with `MTLDevice::location` for GPU type Detection (GPU, macOS)
|
||||
* This should resolve the issue where discrete GPUs were detected as integrated GPUs on Intel MacBooks with multi-GPU configurations.
|
||||
* Prevent text files from being loaded as image files (#1843, Logo)
|
||||
|
||||
Logos:
|
||||
* Add Minimal System
|
||||
* Add AxOS
|
||||
* Rename Ada to Xray OS
|
||||
|
||||
# 2.47.0
|
||||
|
||||
Features:
|
||||
* Various improvements for Solaris / OpenIndiana support
|
||||
* Support BIOS (UEFI or legacy) type detection (BIOS)
|
||||
* Support physical disk detection (PhysicalDisk)
|
||||
* Remove leading `-` from login shells (Shell)
|
||||
* Improve GPU detection performance (GPU)
|
||||
* Drop `libpciaccess` dependency
|
||||
* Use native API to detect sound devices (Sound)
|
||||
* Drop `PulseAudio` dependency
|
||||
* Improve DietPi OS and Raspberry Pi OS detection (#1816, OS, Linux)
|
||||
* Force reporting version 26 on macOS Tahoe (OS, macOS)
|
||||
* Append version string to Ubuntu variants (OS, Linux)
|
||||
* Improve performance of media detection for macOS 15.4+ (Media, macOS)
|
||||
* Increase `PROC_FILE_BUFFSIZ` to avoid possible short reads (Linux)
|
||||
* Fix potential bugs in `DiskIO`, `NetIO` and `CPUUsage` modules
|
||||
* Improve accuracy of CPU usage calculations by including interrupt and softirq times (CPUUsage, Linux / *BSD)
|
||||
* Ignore `init` and `systemd` processes when detecting terminals (Terminal, Linux)
|
||||
* Improve accuracy of CPU usage detection on Windows 10+ with perflib, which matches values reported by Task Manager (CPUUsage, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Fix `pci.ids` file location (#1819, GPU, OpenBSD)
|
||||
* Fix compiling on FreeBSD when `libdrm` support is disabled (#1820, GPU, FreeBSD)
|
||||
|
||||
Logos:
|
||||
* Improve visibility on white-background terminals for some logos by replacing white with the default foreground color
|
||||
* According to Wikipedia, the default foreground color is implementation-defined. It's usually black for white themes and white for dark themes. However, some terminals, notably Konsole with the default theme, use a different color, which may cause issues with some logos.
|
||||
* Add Xubuntu
|
||||
|
||||
# 2.46.0
|
||||
|
||||
Features:
|
||||
* Support Rio terminal font detection (#1789, TerminalFont, Linux)
|
||||
* Support GPU detection by DRM on FreeBSD (GPU, FreeBSD)
|
||||
* Enable by `--gpu-detection-method auto`
|
||||
* Require proper DRM drivers installed and loaded
|
||||
* Support PowerPC CPU detection on NetBSD (#1802, CPU, NetBSD)
|
||||
* Support Aerospace WM detection (#1796, WM, macOS)
|
||||
* Improve Raspberry Pi OS for RPI5 detection (#1773, OS, Linux)
|
||||
* Support Linux Binary Compatibility detection on FreeBSD (#1786, Host, Linux)
|
||||
* Use `board-id` as board name if available (Board, macOS)
|
||||
* Intel only
|
||||
* Support shared VRAM usage detection for AMD GPUs (GPU, Linux)
|
||||
* Use `perflib.h` instead of `pdh.h` for CPU temperature querying to get rid of `pdh.dll` dependency (#1787, CPU, Windows)
|
||||
* Support GPU info detection for old ATI radeon driver (#1810, GPU, Linux)
|
||||
* Add macOS 26 Tahoe support (macOS)
|
||||
* Report macOS 26 code name (OS)
|
||||
* Report Liquid Glass DE on macOS 26+ (DE)
|
||||
* Detect Metal 4 support (GPU)
|
||||
|
||||
Bugfixes:
|
||||
* Fix packages counting by ignoring hidden folders (Packages, OpenBSD)
|
||||
* Fix Hyprland version detection (WM, FreeBSD)
|
||||
* Don't show `Please insert a disk into drive D:` error dialogs (#1805, Disk, Windows)
|
||||
* Hide `/boot/firmware` by default (Disk, Linux)
|
||||
|
||||
Logos:
|
||||
* Rename Hydra Framework to HydraPwk (#1812)
|
||||
* Add AnushOS (#1806)
|
||||
* Add HarmonyOS (#1804)
|
||||
* Add GhostFreak (#1801)
|
||||
* Add TrueNAS Scale (#1795)
|
||||
* Add Fedora2_small (#1785)
|
||||
* Add xenia_old; update colors of xenia (#1797)
|
||||
* Improve colors of bedrock_small (#1790)
|
||||
* Add Kalpa Desktop (#1807)
|
||||
|
||||
# 2.45.0
|
||||
|
||||
Features:
|
||||
* Support OnePlus marketing name detection (#1768, Host, Android)
|
||||
* Recognize additional GPU vendors (GPU, Linux)
|
||||
* Support CTWM, FVWM and I3 window manager version detection (WM)
|
||||
* Support KDE version detection on *BSD (DE, FreeBSD)
|
||||
* Support `"logo": { "type": "command-raw" }` to run a command and display its output as logo (#1780, Logo)
|
||||
* Useful for displaying custom logos generated by other programs such as `pokeget`: `{ "type": "command-raw", "source": "pokeget random --hide-name" }`
|
||||
* Supported in JSONC config file only. `pokeget random --hide-name | fastfetch --file-raw -` should be used in shell.
|
||||
* Acquire SMBIOS information on DragonFly BSD from `/dev/mem`; legacy BIOS only (PhysicalMemory, DragonFly)
|
||||
* Support swap usage detection on DragonFly BSD (Swap, DragonFly)
|
||||
* Support `--swap-separate` to display detailed swap devices on separate lines (Swap)
|
||||
|
||||
Bugfixes
|
||||
* Fix MacBook Air model name (#1779, Host, macOS)
|
||||
* Don't ignore sshfs mountpoints (#1776, Disk, Linux / FreeBSD)
|
||||
* Fix dnf package count detection (#1777, Packages, Linux)
|
||||
|
||||
Logos:
|
||||
* Add Starry Linux (#1771)
|
||||
* Add rhel_small (#1774)
|
||||
* Update color palette of voidlinux (#1775)
|
||||
* Add void2
|
||||
* Update Xenia Linux (#1783)
|
||||
|
||||
# 2.44.0
|
||||
|
||||
Features:
|
||||
* Add option `--disk-hide-folders` and `--disk-hide-fs` to hide specific mountpoints and filesystems in Disk module (Disk)
|
||||
* `--disk-hide-folders` defaults to `/efi:/boot:/boot/efi` on Linux and *BSD. Previously these EFI-related folders were hardcoded to be hidden on Linux.
|
||||
|
||||
Bugfixes:
|
||||
* Fix Apple Terminal compatibility with `--stat` (macOS, #1755)
|
||||
* Ignore `/usr/bin/script` when detecting shell and terminal (Terminal / Shell, #1761)
|
||||
* Fix compatibility with KDE Plasma 6.4 which is in beta currently (Display, Linux, #1765)
|
||||
|
||||
Logos:
|
||||
* Add Kylin (#1760)
|
||||
* Add UBLinux (#1764)
|
||||
|
||||
# 2.43.0
|
||||
|
||||
Features:
|
||||
* Support physical core count and package count detection on Solaris (CPU, SunOS)
|
||||
* Improve physical core count detection on FreeBSD (CPU, FreeBSD)
|
||||
* Add option to hide unknown GPUs (GPU)
|
||||
* Detect VRAM type of AMD GPUs on Linux (GPU, Linux)
|
||||
* Support playing media detection on macOS 15.4 (#1737, Media, macOS)
|
||||
* Whether it works on newer versions is unknown
|
||||
* Detect player name for Windows UMP apps (Media, Windows)
|
||||
|
||||
Bugfixes:
|
||||
* Fix disk usage detection on 32-bit Linux (#1734, Disk, Linux)
|
||||
* Fix compiling on Asahi Linux (GPU, Linux)
|
||||
* Fix duplicated playback status (Media, Linux)
|
||||
* Don't show 255 in custom format when muted on macOS (#1750, Sound, macOS)
|
||||
* Remove shared memory detection for AMD GPUs, which doesn't work as expected (GPU, Windows)
|
||||
|
||||
Logos:
|
||||
* new AthenaOS
|
||||
* add Hydra Framework
|
||||
|
||||
# 2.42.0
|
||||
|
||||
Changes:
|
||||
* Normalize the module name `Bios` to `BIOS` (#1721)
|
||||
* No configuration file changes are required because fastfetch parses module names case-insensitively.
|
||||
|
||||
Bugfixes:
|
||||
* Disable disk type detection for virtual disks (PhysicalDisk, Linux, #1669)
|
||||
* Fix incorrect CPU temperature reporting (CPU, OpenBSD)
|
||||
* Fix setting `logo.chafa.symbols` in JSON configuration (Logo, #1709)
|
||||
* Fix non-normalized time display (Uptime, #1720)
|
||||
* Miscellaneous minor fixes
|
||||
|
||||
Features:
|
||||
* Add CPU temperature detection support (CPU, SunOS)
|
||||
* Improve CPU frequency detection (CPU, NetBSD)
|
||||
* Add Wi-Fi detection support (Wifi, NetBSD)
|
||||
* Add Webcam detection support (Camera, OpenBSD)
|
||||
* Requires root privileges
|
||||
|
||||
Logos:
|
||||
* Remove GoralixOS logo (#1699)
|
||||
* Add Aurora logo (#1700)
|
||||
* Add Codex Linux logo (#1701)
|
||||
|
||||
# 2.41.0
|
||||
|
||||
Changes:
|
||||
* Due to [the deprecation](https://github.com/actions/runner-images/issues/11101), Linux x86_64 binaries are now built with Ubuntu 22.04 (Glibc 2.35, Debian 12)
|
||||
* You can always build fastfetch yourself on your own. Please don't report bugs related to this change.
|
||||
|
||||
Features:
|
||||
* Support physical core count detection on non-x86 platforms (CPU, Linux / FreeBSD)
|
||||
* Support CPU frequency detection on PPC64 (CPU, FreeBSD)
|
||||
* Support soar packages count detection (Packages, Linux)
|
||||
* Support `~` path expanding on Windows (Logo, Windows)
|
||||
* Support retrieving full user name (Title)
|
||||
* Exposed with `--title-format '{full-user-name}'`
|
||||
* Improve CPU (thermal zone) temperature detection on Windows (CPU, Windows)
|
||||
* Administrator privileges are no longer needed
|
||||
* Support base Wifi info detection on OpenBSD (Wifi, OpenBSD)
|
||||
* To be tested
|
||||
* Support GPU temperature detection for Intel dGPU on Linux (GPU, Linux)
|
||||
* To be tested
|
||||
* Add new ARM CPU part numbers (CPU, Linux)
|
||||
* Add base implementation of Bluetooth device detection (Bluetooth, NetBSD, #1690)
|
||||
* Some small improvements
|
||||
|
||||
Logo:
|
||||
* Add anduinos
|
||||
* Add 2 more Alpine logos
|
||||
|
||||
# 2.40.4
|
||||
|
||||
Bugfixes:
|
||||
* Fix loading presets config on Windows (Windows, #1682)
|
||||
* Regression of v2.40.0
|
||||
* Remove the prefix `v` of Hyprland version on Arch Linux (WM, Linux)
|
||||
|
||||
# 2.40.3
|
||||
|
||||
Bugfixes:
|
||||
* Fix loading example configs from presets directory (#1672)
|
||||
* Regression of v2.40.2
|
||||
* Mark kitty image protocol support for warp terminal on macOS too (Logo)
|
||||
|
||||
# 2.40.2
|
||||
|
||||
Changes:
|
||||
* Since v2.40.0, we've been loading config files from the directory where the fastfetch binary is located. However, this approach may lead to loading unexpected files. For example, `fastfetch -c groups` would attempt to load `/usr/bin/groups`. Therefore, we now enforce the `.jsonc` extension when loading config files. Examples:
|
||||
1. `-c filename`: loads `filename.jsonc`
|
||||
2. `-c filename.jsonc`: loads `filename.jsonc`
|
||||
3. `-c filename.json`: loads `filename.json` and enforces strict JSON syntax (no comments or trailing commas)
|
||||
4. `-c filename.ext`: loads `filename.ext.jsonc` (`.jsonc` extension is enforced)
|
||||
|
||||
Features:
|
||||
* Mark kitty image protocol support for warp terminal (Logo)
|
||||
* Documentation improvements
|
||||
|
||||
# 2.40.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix compiling error on old intel platform (TPM, macOS)
|
||||
* Fix `--file-raw -` no longer working (Logo, #1659)
|
||||
* Regression of v2.40.0
|
||||
|
||||
# 2.40.0
|
||||
|
||||
Changes:
|
||||
* In `key-format` of `LocalIP` module, `{name}` has been renamed to `{ifname}` for consistency (LocalIP, #1639)
|
||||
|
||||
Features:
|
||||
* Support Warp Terminal font detection (TerminalFont, Windows)
|
||||
* Support more AMD GPU information using ADL SDK, including memory type detection (GPU, Windows)
|
||||
* Support Intel dGPU memory type detection (GPU, Windows)
|
||||
* Support Nvidia VMEM type detection via NVAPI (GPU, Windows, #993)
|
||||
* Support Boot manager detection for OpenBSD and NetBSD (Bootmgr, OpenBSD / NetBSD)
|
||||
* Use `SystemConfiguration` for DNS entries detection (DNS, macOS)
|
||||
* Add `systemd-resolved` support for DNS module (DNS, Linux, #1646)
|
||||
* Improve performance and accuracy of Wifi detection on FreeBSD using ioctl (Wifi, FreeBSD)
|
||||
* Support remaining time reporting for batteries on NetBSD (Battery, NetBSD)
|
||||
* Add new Mac models support (Host, macOS)
|
||||
* Load config from fastfetch binary path with `--config` option (#1649)
|
||||
* Support TPM detection on macOS (TPM, macOS)
|
||||
* Support IPv6 client address report (Users, Linux / Windows)
|
||||
* Support default route detection for IPv6 (LocalIP, Linux)
|
||||
* Round seconds to the nearest minute to match the behavior of `uptime` command (Uptime)
|
||||
|
||||
Bugfixes:
|
||||
* Fix `outputColor` not working when `length` is set in Separator module (#1644)
|
||||
* Fix CPU detection on PowerPC platforms (#1640, CPU, Linux)
|
||||
* Fix battery manufacture date detection (Battery, macOS)
|
||||
* Fix battery critical state detection (Battery, Linux)
|
||||
* Fix Warp Terminal PID detection (Terminal, macOS)
|
||||
* Remove disk creation time detection support on SunOS as ctim is file status change timestamp, not creation time (Disk, SunOS)
|
||||
* Fall back to KDGKBINFO if `usbhid` fails (Keyboard, FreeBSD)
|
||||
* Fix multiple paging file support (Swap, Windows)
|
||||
* Fix memleaks, code smells in multiple modules
|
||||
* Fix boot time calculation on NetBSD (Uptime, NetBSD)
|
||||
* Temporarily fix Hyprland version detection (WM, Linux, #1657)
|
||||
|
||||
Logo:
|
||||
* Fix opensuse-tumbleweed_small (#1636)
|
||||
* Change WiiLinuxNgx to more generic name with aliases Wii-Linux and WiiLinux (#1633)
|
||||
* Change name of Xray-OS to Ada (#1651)
|
||||
* Change Nexa Linux logo (#1653)
|
||||
|
||||
# 2.39.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix a regression that PublicIP detection fails randomly (PublicIP, #1629)
|
||||
|
||||
# 2.39.0
|
||||
|
||||
Changes:
|
||||
* OSMesa backend for OpenGL detection is removed (#1618)
|
||||
* Fastfetch no longer tries to use the private framework `Apple80211` to acquire SSID for Wifi module, which is only useful for macOS Sonoma (Wifi, macOS)
|
||||
|
||||
Features:
|
||||
* Improve accuracy of HDR support on Windows 11 24H2 (Display, Windows)
|
||||
* Improve performance of SSID detection on macOS Sequoia (Wifi, macOS, #1597)
|
||||
* Support warp terminal version detection on Windows (Terminal, Windows)
|
||||
* Support default route detection on OpenBSD & DragonFly BSD (LocalIP, OpenBSD / DragonFly)
|
||||
* Improve bash completion script
|
||||
* Improve performance of networking (PublicIP / Weather)
|
||||
* Support pkgsrc package manager detection on Linux (Packages, Linux)
|
||||
|
||||
Logo:
|
||||
* Add Common Torizon OS
|
||||
* Change FoxOS to WolfOS
|
||||
* Add Bredos
|
||||
* Add NetBSD2
|
||||
|
||||
# 2.38.0
|
||||
|
||||
Bugfixes:
|
||||
* Fix empty battery slots handling (Battery, Haiku, #1575)
|
||||
* Fix `{day-pretty}` output in custom format (DateTime, Windows)
|
||||
* Fix VanillaOS detection (OS, Linux)
|
||||
* Fix secure boot testing (Bootmgr, Linux, #1584)
|
||||
* Fix the SI unit "kB" in help message (#1589)
|
||||
* Fix segfault on macOS 10.15 when using the binary downloaded from Github Releases (Camera, macOS, #1594)
|
||||
|
||||
Features:
|
||||
* Support Chassis module in macOS (Chassis, macOS)
|
||||
* Allow customize key format with kernel name and distro name (OS)
|
||||
* Add missing `{icon}` in custom key format (Battery)
|
||||
* Add missing `{mountpoint}` and `{mount-from}` in custom output format (Disk, #1577)
|
||||
* Support percentage num & bar in custom format (GPU, #1583)
|
||||
* Support `pisi` package manager detection (Packages, Linux)
|
||||
* Support termite terminal font detection (TerminalFont, Linux)
|
||||
* Report monitor type in Brightness module (Brightness)
|
||||
|
||||
Logo:
|
||||
* Add `opensuse-tumbleweed_small`
|
||||
* Add `Bedrock_small`
|
||||
* Add `fastfetch`
|
||||
* Remove some unnecessary distro names
|
||||
|
||||
# 2.37.0
|
||||
|
||||
Changes:
|
||||
* Option `--escape-bedrock` is removed. The function is always enabled now.
|
||||
|
||||
Features:
|
||||
* Support for Haiku is greatly improved (Haiku)
|
||||
* CPU, GPU, Disk, Sound, Terminal, Terminal Font, Init System, Battery, Mouse, Keyboard, NetIO, CPU Usage, Physical Disk and OpenGL should work on Haiku now
|
||||
* SMBIOS related modules (Host, Bios, Board, Chassis, Physical Memory) should work in platforms with legacy BIOS system.
|
||||
* Support for Gamepad and Bluetooth are WIP.
|
||||
* Some bugs are found and fixed.
|
||||
* Remove `python-requests` dependency in `scripts/gen-*.py`.
|
||||
* Add cmake option `-DENABLE_EMBEDDED_AMDGPUIDS=BOOL` (disabled by default)
|
||||
* If enabled, fastfetch will embed the newest [`amdgpu.ids`](https://gitlab.freedesktop.org/mesa/drm/-/blob/main/data/amdgpu.ids?ref_type=heads) file into fastfetch binary.
|
||||
* Weather module now honors `display.temp.unit` option (#1560, Weather)
|
||||
* Support Physical Memory module in NetBSD (PhysicalMemory, NetBSD)
|
||||
* Requires root permission
|
||||
* Improve non-intel CPU detection in NetBSD (#1573, CPU, NetBSD)
|
||||
|
||||
Bugfixes:
|
||||
* Fix building in macOS 10.13 (GPU, macOS)
|
||||
* Properly round percent values when detecting volume (#1558, Sound)
|
||||
* Fix Physical Memory module doesn't work in `--format json` mode
|
||||
* Add some missing variable inits (GPU, Linux)
|
||||
* Fix `--localip-default-route-only false` not working with `--gen-config` (#1570, LocalIP)
|
||||
|
||||
Logo:
|
||||
* Update Rosa linux
|
||||
* Add Haiku2
|
||||
|
||||
# 2.36.1
|
||||
|
||||
Changes:
|
||||
* To use [the native arm64 runner of Github Action](https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/), Linux aarch64 binary is built with Ubuntu 22.04 (Glibc 2.35, Debian 12).
|
||||
|
||||
Bugfixes:
|
||||
* Chimera Linux logo is now displayed correctly (#1554, Logo)
|
||||
* Regression of 2.36.0
|
||||
* Fix building on Haiku
|
||||
|
||||
Logo:
|
||||
* Fix ALT Linux
|
||||
|
||||
# 2.36.0
|
||||
|
||||
Bugfixes:
|
||||
* Trim leading slash for login shells (Shell, OpenBSD)
|
||||
* Prefer SOC name if available over CPU name (CPU, Linux)
|
||||
|
||||
Features:
|
||||
* Use kernel API to detect sound devices (Sound, NetBSD)
|
||||
* Use sndio for sound server detection on OpenBSD (Sound, OpenBSD)
|
||||
* Add minimal implementation for Haiku (#1538, Haiku)
|
||||
* Support CPU & GPU temperature detection for M4x (CPU / GPU, macOS)
|
||||
* Support VMEM size detection for old Nvidia cards (GPU, Linux)
|
||||
* Use [recommendedMaxWorkingSetSize](https://developer.apple.com/documentation/metal/mtldevice/recommendedmaxworkingsetsize) as total GPU mem size (GPU, macOS)
|
||||
* Support Physical core count and CPU package count detection for loongarch (CPU, Linux)
|
||||
* Split ID_LIKE when used for distro matching (#1540, Logo)
|
||||
* Capitalize `{type}`'s first letter in custom format (#1543, Display)
|
||||
* Support model name detection for s390x (CPU, Linux)
|
||||
* Support more Armbian variants detection (#1547, OS, Linux)
|
||||
* Support the syntax of `{$ENV_VAR}` in custom format, which will be replaced by the value of the environment variable `ENV_VAR` (#1541)
|
||||
* This is another way to pass 3rd-party data to fastfetch besides `Custom` module.
|
||||
* Improve performance of Tilix version detection (Terminal, Linux)
|
||||
|
||||
Logo:
|
||||
* Update arch_old
|
||||
* Add Nexa Linux
|
||||
* Add filotimo
|
||||
* Update some distro names
|
||||
|
||||
# 2.35.0
|
||||
|
||||
Bugfixes:
|
||||
* 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.
|
||||
@@ -89,7 +651,7 @@ Features:
|
||||
* Support tilix version detection (Terminal, Linux)
|
||||
* Support percent type config in module level. Example:
|
||||
|
||||
```json
|
||||
```jsonc
|
||||
{
|
||||
"type": "memory",
|
||||
"percent": {
|
||||
@@ -529,7 +1091,7 @@ Bugfixes:
|
||||
* Fix some presets
|
||||
* Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux)
|
||||
* Remove debug output (#1097, Windows)
|
||||
* Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix flag `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix wrong date on Raspbian 10 (#1108, DateTime, Linux)
|
||||
* Use `brightness` instead of `actuall_brightness` when detecting current brightness level (Brightness, Linux)
|
||||
* Ref: https://bugzilla.kernel.org/show_bug.cgi?id=203905
|
||||
|
||||
+293
-105
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.32.1
|
||||
VERSION 2.48.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -30,6 +30,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
|
||||
set(DragonFly TRUE CACHE BOOL "..." FORCE)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
|
||||
set(SunOS TRUE CACHE BOOL "..." FORCE)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku")
|
||||
set(Haiku TRUE CACHE BOOL "..." FORCE)
|
||||
elseif(NOT APPLE AND NOT WIN32)
|
||||
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
|
||||
endif()
|
||||
@@ -54,43 +56,44 @@ include(CheckIncludeFile)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR WIN32 OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR APPLE OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "NetBSD OR OpenBSD" OFF)
|
||||
|
||||
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
|
||||
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
|
||||
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
|
||||
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
|
||||
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
|
||||
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
|
||||
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
|
||||
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
|
||||
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
|
||||
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
|
||||
|
||||
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
|
||||
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
|
||||
@@ -99,7 +102,7 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
|
||||
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
|
||||
endif()
|
||||
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PKG PKGTOOL RPM SCOOP SNAP SORCERY WINGET XBPS)
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SOAR SORCERY WINGET XBPS)
|
||||
foreach(package_manager ${PACKAGE_MANAGERS})
|
||||
if(package_manager STREQUAL "WINGET")
|
||||
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
|
||||
@@ -133,12 +136,12 @@ else()
|
||||
message(STATUS "Threads type: disabled")
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type")
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=return-type -Werror=vla")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion")
|
||||
|
||||
if(WIN32 OR ENABLE_DIRECTX_HEADERS)
|
||||
if(WIN32 OR Haiku OR ENABLE_DIRECTX_HEADERS)
|
||||
enable_language(CXX)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}")
|
||||
@@ -268,11 +271,16 @@ endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
|
||||
if(Python_FOUND)
|
||||
if(NOT EXISTS "${PROJECT_BINARY_DIR}/pci.ids")
|
||||
message(STATUS "'${PROJECT_BINARY_DIR}/pci.ids' is missing, downloading...")
|
||||
file(DOWNLOAD "https://pci-ids.ucw.cz/v2.2/pci.ids" "${PROJECT_BINARY_DIR}/pci.ids")
|
||||
endif()
|
||||
message(STATUS "Generating 'fastfetch_pciids.c.inc'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py"
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" "${PROJECT_BINARY_DIR}/pci.ids"
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc"
|
||||
RESULT_VARIABLE PYTHON_PCIIDS_RETCODE)
|
||||
if(NOT PYTHON_PCIIDS_RETCODE EQUAL 0)
|
||||
file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_pciids.c.inc")
|
||||
message(FATAL_ERROR "Failed to generate 'fastfetch_pciids.c.inc'")
|
||||
endif()
|
||||
else()
|
||||
@@ -281,6 +289,26 @@ if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_pciids
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS AND NOT EXISTS "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
|
||||
if(Python_FOUND)
|
||||
if(NOT EXISTS "${PROJECT_BINARY_DIR}/amdgpu.ids")
|
||||
message(STATUS "'${PROJECT_BINARY_DIR}/amdgpu.ids' is missing, downloading...")
|
||||
file(DOWNLOAD "https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids" "${PROJECT_BINARY_DIR}/amdgpu.ids")
|
||||
endif()
|
||||
message(STATUS "Generating 'fastfetch_amdgpuids.c.inc'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-amdgpuids.py" "${PROJECT_BINARY_DIR}/amdgpu.ids"
|
||||
OUTPUT_FILE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc"
|
||||
RESULT_VARIABLE PYTHON_AMDGPUIDS_RETCODE)
|
||||
if(NOT PYTHON_AMDGPUIDS_RETCODE EQUAL 0)
|
||||
file(REMOVE "${PROJECT_BINARY_DIR}/fastfetch_amdgpuids.c.inc")
|
||||
message(FATAL_ERROR "Failed to generate 'fastfetch_amdgpuids.c.inc'")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Python3 is not found, 'fastfetch_amdgpuids.c.inc' will not be generated")
|
||||
set(ENABLE_EMBEDDED_AMDGPUIDS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(Python_FOUND)
|
||||
message(STATUS "Generating 'fastfetch.1'")
|
||||
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-man.py"
|
||||
@@ -297,9 +325,6 @@ endif()
|
||||
|
||||
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
|
||||
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
|
||||
fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER)
|
||||
fastfetch_load_text(src/data/help_color.txt DATATEXT_HELP_COLOR)
|
||||
fastfetch_load_text(src/data/help_format.txt DATATEXT_HELP_FORMAT)
|
||||
|
||||
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
|
||||
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
|
||||
@@ -311,13 +336,12 @@ endif()
|
||||
# Ascii image data #
|
||||
####################
|
||||
|
||||
file(GLOB LOGO_FILES "src/logo/ascii/*.txt")
|
||||
file(GLOB LOGO_FILES CONFIGURE_DEPENDS "src/logo/ascii/*.txt")
|
||||
set(LOGO_BUILTIN_H "#pragma once\n#pragma GCC diagnostic ignored \"-Wtrigraphs\"\n\n")
|
||||
foreach(file ${LOGO_FILES})
|
||||
fastfetch_load_text("${file}" content)
|
||||
get_filename_component(file "${file}" NAME_WE)
|
||||
string(TOUPPER "${file}" file)
|
||||
string(REGEX REPLACE "\\$\\{c([0-9]+)\\}" "$\\1" content "${content}")
|
||||
set(LOGO_BUILTIN_H "${LOGO_BUILTIN_H}#define FASTFETCH_DATATEXT_LOGO_${file} ${content}\n")
|
||||
endforeach()
|
||||
file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
|
||||
@@ -336,6 +360,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/library.c
|
||||
src/common/modules.c
|
||||
src/common/netif/netif.c
|
||||
src/common/networking/networking_common.c
|
||||
src/common/option.c
|
||||
src/common/parsing.c
|
||||
src/common/printing.c
|
||||
@@ -464,7 +489,7 @@ if(LINUX)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
@@ -499,6 +524,7 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
@@ -533,7 +559,7 @@ if(LINUX)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_linux.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
@@ -545,7 +571,7 @@ elseif(ANDROID)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_linux.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_android.c
|
||||
src/detection/bios/bios_android.c
|
||||
@@ -611,13 +637,12 @@ elseif(FreeBSD)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_bsd.c
|
||||
src/detection/bios/bios_bsd.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/board/board_bsd.c
|
||||
src/detection/bootmgr/bootmgr_bsd.c
|
||||
src/detection/brightness/brightness_bsd.c
|
||||
@@ -647,6 +672,7 @@ elseif(FreeBSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
@@ -680,8 +706,7 @@ elseif(FreeBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_bsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
@@ -689,31 +714,42 @@ elseif(FreeBSD)
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
if(DragonFly)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
)
|
||||
else()
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/detection/bluetooth/bluetooth_bsd.c
|
||||
src/detection/wifi/wifi_bsd.c
|
||||
)
|
||||
endif()
|
||||
elseif(NetBSD)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/battery/battery_nbsd.c
|
||||
src/detection/bios/bios_nbsd.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_linux.c
|
||||
src/detection/bluetooth/bluetooth_bsd.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/board/board_nbsd.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/bootmgr/bootmgr_bsd.c
|
||||
src/detection/brightness/brightness_nbsd.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_nbsd.c
|
||||
src/detection/cpu/cpu_nbsd.c
|
||||
src/detection/cpucache/cpucache_nosupport.c
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_nbsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
@@ -743,16 +779,16 @@ elseif(NetBSD)
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_nosupport.c
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_obsd.c
|
||||
src/detection/memory/memory_nbsd.c
|
||||
src/detection/mouse/mouse_nosupport.c
|
||||
src/detection/netio/netio_bsd.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_nbsd.c
|
||||
src/detection/packages/packages_obsd.c
|
||||
src/detection/packages/packages_nbsd.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_nbsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_nbsd.c
|
||||
src/detection/swap/swap_obsd.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -762,8 +798,8 @@ elseif(NetBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wifi/wifi_nbsd.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
@@ -776,26 +812,26 @@ elseif(OpenBSD)
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/bluetoothradio/bluetoothradio_linux.c
|
||||
src/detection/board/board_nosupport.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/battery/battery_obsd.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_bsd.c
|
||||
src/detection/brightness/brightness_obsd.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_obsd.c
|
||||
src/detection/cpucache/cpucache_nosupport.c
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_bsd.c
|
||||
src/detection/cursor/cursor_linux.c
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_nosupport.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_obsd.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
src/detection/displayserver/linux/drm.c
|
||||
@@ -834,7 +870,7 @@ elseif(OpenBSD)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_obsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_obsd.c
|
||||
src/detection/swap/swap_obsd.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -844,20 +880,21 @@ elseif(OpenBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_obsd.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wifi/wifi_obsd.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/smbiosHelper.c
|
||||
)
|
||||
elseif(APPLE)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_apple.c
|
||||
@@ -868,13 +905,13 @@ elseif(APPLE)
|
||||
src/detection/bootmgr/bootmgr_apple.c
|
||||
src/detection/brightness/brightness_apple.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/chassis/chassis_apple.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
src/detection/cpucache/cpucache_apple.c
|
||||
src/detection/cpuusage/cpuusage_apple.c
|
||||
src/detection/cursor/cursor_apple.m
|
||||
src/detection/disk/disk_bsd.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/dns/dns_apple.c
|
||||
src/detection/physicaldisk/physicaldisk_apple.c
|
||||
src/detection/physicalmemory/physicalmemory_apple.m
|
||||
src/detection/diskio/diskio_apple.c
|
||||
@@ -908,12 +945,12 @@ elseif(APPLE)
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalsize/terminalsize_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/tpm/tpm_nosupport.c
|
||||
src/detection/tpm/tpm_apple.c
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_apple.m
|
||||
src/detection/wifi/wifi_apple.m
|
||||
src/detection/wm/wm_apple.c
|
||||
src/detection/wm/wm_apple.m
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
@@ -928,7 +965,7 @@ elseif(WIN32)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/io/io_windows.c
|
||||
src/common/netif/netif_windows.c
|
||||
src/common/networking_windows.c
|
||||
src/common/networking/networking_windows.c
|
||||
src/common/processing_windows.c
|
||||
src/detection/battery/battery_windows.c
|
||||
src/detection/bios/bios_windows.c
|
||||
@@ -941,7 +978,6 @@ elseif(WIN32)
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
src/detection/cpu/cpu_windows.cpp
|
||||
src/detection/cpucache/cpucache_windows.c
|
||||
src/detection/cpuusage/cpuusage_windows.c
|
||||
src/detection/cursor/cursor_windows.c
|
||||
@@ -994,15 +1030,17 @@ elseif(WIN32)
|
||||
src/util/windows/registry.c
|
||||
src/util/windows/unicode.c
|
||||
src/util/windows/wmi.cpp
|
||||
src/util/windows/version.c
|
||||
src/util/platform/FFPlatform_windows.c
|
||||
src/util/binary_windows.c
|
||||
src/util/debug_windows.c
|
||||
)
|
||||
elseif(SunOS)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_bsd.c
|
||||
src/common/networking_linux.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_nosupport.c
|
||||
src/detection/bios/bios_windows.c
|
||||
@@ -1019,7 +1057,7 @@ elseif(SunOS)
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/disk/disk_sunos.c
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_nosupport.c
|
||||
src/detection/physicaldisk/physicaldisk_sunos.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_sunos.c
|
||||
src/detection/displayserver/linux/displayserver_linux.c
|
||||
@@ -1059,7 +1097,7 @@ elseif(SunOS)
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_linux.c
|
||||
src/detection/sound/sound_sunos.c
|
||||
src/detection/swap/swap_sunos.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
@@ -1078,6 +1116,76 @@ elseif(SunOS)
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
elseif(Haiku)
|
||||
list(APPEND LIBFASTFETCH_SRC
|
||||
src/common/dbus.c
|
||||
src/common/io/io_unix.c
|
||||
src/common/netif/netif_haiku.c
|
||||
src/common/networking/networking_linux.c
|
||||
src/common/processing_linux.c
|
||||
src/detection/battery/battery_haiku.c
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_haiku.c
|
||||
src/detection/cpucache/cpucache_shared.c
|
||||
src/detection/cpuusage/cpuusage_haiku.c
|
||||
src/detection/cursor/cursor_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_haiku.cpp
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/disk/disk_haiku.cpp
|
||||
src/detection/dns/dns_linux.c
|
||||
src/detection/physicaldisk/physicaldisk_haiku.c
|
||||
src/detection/physicalmemory/physicalmemory_linux.c
|
||||
src/detection/diskio/diskio_nosupport.c
|
||||
src/detection/displayserver/displayserver_haiku.cpp
|
||||
src/detection/font/font_haiku.cpp
|
||||
src/detection/gpu/gpu_haiku.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_windows.c
|
||||
src/detection/icons/icons_nosupport.c
|
||||
src/detection/initsystem/initsystem_haiku.c
|
||||
src/detection/keyboard/keyboard_haiku.cpp
|
||||
src/detection/libc/libc_nosupport.c
|
||||
src/detection/lm/lm_nosupport.c
|
||||
src/detection/loadavg/loadavg_nosupport.c
|
||||
src/detection/locale/locale_linux.c
|
||||
src/detection/localip/localip_linux.c
|
||||
src/detection/gamepad/gamepad_haiku.cpp
|
||||
src/detection/media/media_linux.c
|
||||
src/detection/memory/memory_haiku.c
|
||||
src/detection/mouse/mouse_haiku.cpp
|
||||
src/detection/netio/netio_haiku.cpp
|
||||
src/detection/opengl/opengl_haiku.cpp
|
||||
src/detection/os/os_haiku.c
|
||||
src/detection/packages/packages_haiku.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_haiku.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_haiku.cpp
|
||||
src/detection/swap/swap_haiku.c
|
||||
src/detection/terminalfont/terminalfont_linux.c
|
||||
src/detection/terminalshell/terminalshell_linux.c
|
||||
src/detection/terminalsize/terminalsize_linux.c
|
||||
src/detection/theme/theme_nosupport.c
|
||||
src/detection/tpm/tpm_nosupport.c
|
||||
src/detection/uptime/uptime_haiku.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_nosupport.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/haiku/version.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DIRECTX_HEADERS)
|
||||
@@ -1102,6 +1210,9 @@ endif()
|
||||
if(LINUX)
|
||||
check_function_exists(statx HAVE_STATX)
|
||||
endif()
|
||||
if(NOT WIN32)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SYSTEM_YYJSON)
|
||||
find_package(yyjson)
|
||||
@@ -1132,6 +1243,14 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib64 -Wl,-rpath,/system/lib64")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/vendor/lib -Wl,-rpath,/system/lib")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX AND EXISTS "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1")
|
||||
execute_process(COMMAND "/lib/ld-musl-${CMAKE_HOST_SYSTEM_PROCESSOR}.so.1"
|
||||
ERROR_VARIABLE LD_MUSL_RESULT)
|
||||
@@ -1188,6 +1307,8 @@ elseif(NetBSD)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-char-subscripts")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/usr/X11R7/lib -Wl,-rpath,/usr/pkg/lib") # ditto
|
||||
elseif(Haiku)
|
||||
target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE)
|
||||
endif()
|
||||
|
||||
if(FreeBSD OR OpenBSD OR NetBSD)
|
||||
@@ -1208,6 +1329,10 @@ if(HAVE_WCWIDTH)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH)
|
||||
endif()
|
||||
|
||||
if(HAVE_PIPE2)
|
||||
target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PIPE2)
|
||||
endif()
|
||||
|
||||
if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH})
|
||||
@@ -1220,6 +1345,10 @@ if(NOT "${CUSTOM_OS_RELEASE_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of os_release: ${CUSTOM_OS_RELEASE_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_OS_RELEASE_PATH=${CUSTOM_OS_RELEASE_PATH})
|
||||
endif()
|
||||
if(NOT "${CUSTOM_LSB_RELEASE_PATH}" STREQUAL "")
|
||||
message(STATUS "Custom file path of lsb_release: ${CUSTOM_LSB_RELEASE_PATH}")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_LSB_RELEASE_PATH=${CUSTOM_LSB_RELEASE_PATH})
|
||||
endif()
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
message(STATUS "Enabling custom link type: ${BINARY_LINK_TYPE}")
|
||||
@@ -1349,10 +1478,6 @@ else()
|
||||
"GL"
|
||||
)
|
||||
endif()
|
||||
ff_lib_enable(OSMESA
|
||||
"osmesa"
|
||||
"OSMesa"
|
||||
)
|
||||
ff_lib_enable(OPENCL
|
||||
"OpenCL"
|
||||
"OpenCL"
|
||||
@@ -1410,6 +1535,9 @@ endif()
|
||||
if(ENABLE_EMBEDDED_PCIIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1)
|
||||
endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1443,7 +1571,6 @@ elseif(APPLE)
|
||||
PRIVATE "-F /System/Library/PrivateFrameworks"
|
||||
PRIVATE "-weak_framework DisplayServices"
|
||||
PRIVATE "-weak_framework MediaRemote"
|
||||
PRIVATE "-weak_framework Apple80211"
|
||||
)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1455,18 +1582,25 @@ elseif(WIN32)
|
||||
PRIVATE "ws2_32"
|
||||
PRIVATE "ntdll"
|
||||
PRIVATE "version"
|
||||
PRIVATE "setupapi"
|
||||
PRIVATE "hid"
|
||||
PRIVATE "wtsapi32"
|
||||
PRIVATE "imagehlp"
|
||||
PRIVATE "cfgmgr32"
|
||||
PRIVATE "winbrand"
|
||||
PRIVATE "propsys"
|
||||
PRIVATE "secur32"
|
||||
)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
# WoA only works on Windows 10 or higher
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "mincore"
|
||||
)
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "usbhid"
|
||||
PRIVATE "bluetooth"
|
||||
)
|
||||
if(NOT DragonFly)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1481,10 +1615,13 @@ elseif(OpenBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
PRIVATE "kvm"
|
||||
PRIVATE "sndio"
|
||||
)
|
||||
elseif(NetBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "bluetooth"
|
||||
PRIVATE "m"
|
||||
PRIVATE "prop"
|
||||
)
|
||||
elseif(SunOS)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1494,6 +1631,7 @@ elseif(SunOS)
|
||||
PRIVATE "proc"
|
||||
PRIVATE "zfs"
|
||||
PRIVATE "nvpair"
|
||||
PRIVATE "devinfo"
|
||||
)
|
||||
elseif(ANDROID)
|
||||
CHECK_LIBRARY_EXISTS(-l:libandroid-wordexp.a wordexp "" HAVE_LIBANDROID_WORDEXP_STATIC)
|
||||
@@ -1509,6 +1647,17 @@ elseif(ANDROID)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
elseif(Haiku)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "network"
|
||||
PRIVATE "bnetapi"
|
||||
PRIVATE "media"
|
||||
PRIVATE "device"
|
||||
PRIVATE "bluetooth"
|
||||
PRIVATE "GL"
|
||||
PRIVATE "be"
|
||||
PRIVATE "gnu"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(libfastfetch
|
||||
@@ -1611,41 +1760,52 @@ target_link_libraries(fastfetch
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(flashfetch
|
||||
src/flashfetch.c
|
||||
)
|
||||
target_compile_definitions(flashfetch
|
||||
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
|
||||
)
|
||||
target_link_libraries(flashfetch
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
# Prevent fastfetch from linking to libstdc++
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
|
||||
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
|
||||
set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(fastfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
)
|
||||
target_sources(flashfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_options(fastfetch
|
||||
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
|
||||
)
|
||||
target_link_options(flashfetch
|
||||
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BINARY_LINK_TYPE STREQUAL "static")
|
||||
target_link_options(fastfetch PRIVATE "-static")
|
||||
target_link_options(flashfetch PRIVATE "-static")
|
||||
endif()
|
||||
|
||||
# Apply all above parameters to flashfetch if it is built
|
||||
if (BUILD_FLASHFETCH)
|
||||
add_executable(flashfetch
|
||||
src/flashfetch.c
|
||||
)
|
||||
target_compile_definitions(flashfetch
|
||||
PRIVATE FASTFETCH_TARGET_BINARY_NAME=flashfetch
|
||||
)
|
||||
target_link_libraries(flashfetch
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(WIN32)
|
||||
target_sources(flashfetch
|
||||
PRIVATE src/util/windows/version.rc
|
||||
)
|
||||
elseif(APPLE)
|
||||
target_link_options(flashfetch
|
||||
PRIVATE LINKER:-sectcreate,__TEXT,__info_plist,Info.plist
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BINARY_LINK_TYPE STREQUAL "static")
|
||||
target_link_options(flashfetch PRIVATE "-static")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###################
|
||||
@@ -1674,10 +1834,26 @@ if (BUILD_TESTS)
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-color
|
||||
tests/color.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-color
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-duration
|
||||
tests/duration.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-duration
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
|
||||
add_test(NAME test-list COMMAND fastfetch-test-list)
|
||||
add_test(NAME test-format COMMAND fastfetch-test-format)
|
||||
add_test(NAME test-color COMMAND fastfetch-test-color)
|
||||
add_test(NAME test-duration COMMAND fastfetch-test-duration)
|
||||
endif()
|
||||
|
||||
##################
|
||||
@@ -1687,10 +1863,17 @@ endif()
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(
|
||||
TARGETS fastfetch flashfetch
|
||||
TARGETS fastfetch
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
||||
|
||||
if (TARGET flashfetch)
|
||||
install(
|
||||
TARGETS flashfetch
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (TARGET ffwinrt)
|
||||
install(
|
||||
TARGETS ffwinrt
|
||||
@@ -1738,17 +1921,17 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
||||
endif()
|
||||
if(APPLE)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME)
|
||||
else() # We don't use this in Windows
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
endif()
|
||||
if(IS_MUSL)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
|
||||
elseif(IS_MUSL)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
@@ -1774,12 +1957,17 @@ if(LINUX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(HAVE_RPMBUILD "rpmbuild")
|
||||
if(HAVE_RPMBUILD)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
if(NOT IS_MUSL)
|
||||
find_program(HAVE_RPMBUILD "rpmbuild")
|
||||
if(HAVE_RPMBUILD)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
endif()
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
set(CPACK_FREEBSD_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};FREEBSD")
|
||||
endif()
|
||||
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-2023 Linus Dierheimer
|
||||
Copyright (c) 2022-2024 Carter Li
|
||||
Copyright (c) 2022-2025 Carter Li
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
[](https://github.com/fastfetch-cli/fastfetch/releases)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it prettily. It is written mainly in C, with performance and customizability in mind. Currently, Linux, Android, FreeBSD, macOS, SunOS and Windows 7+ are supported.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -21,13 +22,19 @@ Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for
|
||||
<img src="screenshots/example3.png" width="48%" align="top" />
|
||||
<img src="screenshots/example5.png" height="15%" align="top" />
|
||||
|
||||
According configuration files for examples are located [here](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets/examples).
|
||||
|
||||
There are [screenshots on different platforms](https://github.com/fastfetch-cli/fastfetch/wiki).
|
||||
|
||||
## Installation
|
||||
|
||||
### Linux
|
||||
|
||||
Some distros package an outdated fastfetch version. Older versions receive no support, so please try always to use the latest version.
|
||||
Some distributions package outdated versions of fastfetch. Older versions receive no support, so please always try to use the latest version.
|
||||
|
||||
<a href="https://repology.org/project/fastfetch/versions">
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
@@ -45,11 +52,9 @@ Some distros package an outdated fastfetch version. Older versions receive no su
|
||||
* Void Linux: `xbps-install fastfetch`
|
||||
* Venom Linux: `scratch install fastfetch`
|
||||
|
||||
You may need `sudo`, `doas` or `sup` to run these commands.
|
||||
You may need `sudo`, `doas`, or `sup` to run these commands.
|
||||
|
||||
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging).
|
||||
|
||||
If fastfetch is not packaged for your distro or an outdated version is packaged, [linuxbrew](https://brew.sh/) is a good alternative: `brew install fastfetch`
|
||||
If fastfetch is not packaged for your distribution or an outdated version is packaged, [linuxbrew](https://brew.sh/) is a good alternative: `brew install fastfetch`
|
||||
|
||||
### macOS
|
||||
|
||||
@@ -65,72 +70,67 @@ If fastfetch is not packaged for your distro or an outdated version is packaged,
|
||||
|
||||
You may also download the program directly from [the GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) in the form of an archive file.
|
||||
|
||||
### FreeBSD
|
||||
### BSD systems
|
||||
|
||||
* `pkg install fastfetch`
|
||||
* FreeBSD: `pkg install fastfetch`
|
||||
* NetBSD: `pkgin in fastfetch`
|
||||
* OpenBSD: `pkg_add fastfetch` (Snapshots only)
|
||||
* DragonFly BSD: `pkg install fastfetch` (Snapshots only)
|
||||
|
||||
### Android (Termux)
|
||||
|
||||
* `pkg install fastfetch`
|
||||
|
||||
### Nightly
|
||||
|
||||
<https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview>
|
||||
|
||||
## Build from source
|
||||
|
||||
See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building
|
||||
See the 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 interests you: `fastfetch -c all.jsonc`
|
||||
* Find all data that fastfetch detects: `fastfetch -s <module> --format json`
|
||||
* Run with default configuration: `fastfetch`
|
||||
* Run with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) to find what interests you: `fastfetch -c all.jsonc`
|
||||
* View all data that fastfetch detects: `fastfetch -s <module1>[:<module2>][:<module3>] --format json`
|
||||
* Display help messages: `fastfetch --help`
|
||||
* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --gen-config`
|
||||
* Generate a config file based on command line arguments: `fastfetch --arg1 --arg2 --gen-config`
|
||||
|
||||
## Customization
|
||||
|
||||
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.
|
||||
Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for details](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). There are some premade config files in the [`presets`](presets) directory, including those used for the screenshots above. You can load them using `-c <filename>`. These files can serve as examples of the configuration syntax.
|
||||
|
||||
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
|
||||
|
||||
|
||||
## Packaging
|
||||
|
||||
### Repositories
|
||||
|
||||
[](https://repology.org/project/fastfetch/versions)
|
||||
|
||||
### Manual
|
||||
|
||||
* DEB / RPM package: `cmake --build . --target package`
|
||||
* Install directly: `cmake --install . --prefix /usr/local`
|
||||
|
||||
## FAQ
|
||||
|
||||
### Q: Neofetch is good enough. Why do I need fastfetch?
|
||||
|
||||
1. Fastfetch is actively maintained.
|
||||
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.
|
||||
2. Fastfetch is faster, as the name suggests.
|
||||
3. Fastfetch has a greater number of features, though by default it only has a few modules enabled; use `fastfetch -c all` to discover 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 `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!
|
||||
### Q: Fastfetch shows my local IP address. Does it leak my privacy?
|
||||
|
||||
A local IP (10.x.x.x, 172.x.x.x, 192.168.x.x) has nothing to do with privacy. It only makes sense if you are on the same network, for example, if you connect to the same Wi-Fi network.
|
||||
A local IP address (10.x.x.x, 172.x.x.x, 192.168.x.x) has nothing to do with privacy. It only has meaning if you are on the same network, for example, if you connect to the same Wi-Fi network.
|
||||
|
||||
Actually the `Local IP` module is the most useful module for me personally. I (@CarterLi) have several VMs installed to test fastfetch and often need to SSH into them. I have fastfetch running on shell startup and I never need to type `ip addr` manually.
|
||||
Actually, the `Local IP` module is the most useful module for me personally. I (@CarterLi) have several VMs installed to test fastfetch and often need to SSH into them. With fastfetch running on shell startup, I never need to type `ip addr` manually.
|
||||
|
||||
If you really don't like it, you can disable the `Local IP` module in `config.jsonc`.
|
||||
|
||||
### Q: Where is the config file? I can't find it.
|
||||
|
||||
`Fastfetch` does not generate config file automatically. You can use `fastfetch --gen-config` to generate one. The config file will be saved in `~/.config/fastfetch/config.jsonc` by default. See [Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration).
|
||||
Fastfetch does not generate a config file automatically. You can use `fastfetch --gen-config` to generate one. The config file will be saved in `~/.config/fastfetch/config.jsonc` by default. See the [Wiki for details](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration).
|
||||
|
||||
### Q: The configuration is so complex. Where is the documentation?
|
||||
|
||||
Fastfetch uses JSON (with comments) for configuration. I suggest you use an IDE with JSON schema support (like VSCode) to edit it.
|
||||
Fastfetch uses JSON (with comments) for configuration. I suggest using an IDE with JSON schema support (like VSCode) to edit it.
|
||||
|
||||
Alternatively, you can refer to the presets in [`presets` directory](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets).
|
||||
Alternatively, you can refer to the presets in the [`presets` directory](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets).
|
||||
|
||||
The **correct** way to edit the configuration:
|
||||
|
||||
@@ -140,32 +140,32 @@ This is an example that [changes size prefix from MiB / GiB to MB / GB](https://
|
||||
|
||||
### Q: I WANT THE DOCUMENTATION!
|
||||
|
||||
[Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema). It is generated from [JSON schema](https://github.com/fastfetch-cli/fastfetch/blob/dev/doc/json_schema.json) but you won't like it.
|
||||
[Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema). It is generated from the [JSON schema](https://github.com/fastfetch-cli/fastfetch/blob/dev/doc/json_schema.json), but you might not find it very user-friendly.
|
||||
|
||||
### Q: How can I customize the module output?
|
||||
|
||||
Fastfetch uses `format` to generate output. For example, to make the `GPU` module show only the GPU name (leaving other information undisplayed), you can use
|
||||
Fastfetch uses `format` to generate output. For example, to make the `GPU` module show only the GPU name (leaving other information undisplayed), you can use:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"type": "gpu",
|
||||
"format": "{name}" // See `fastfetch -h gpu-format` for detail
|
||||
"format": "{name}" // See `fastfetch -h gpu-format` for details
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
. . which is equivalent to `fastfetch -s gpu --gpu-format '{name}'`
|
||||
...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`
|
||||
See `fastfetch -h format` for information on basic usage. For module-specific formatting, see `fastfetch -h <module>-format`
|
||||
|
||||
### Q: I have my own ascii-art / image file. How can I show it with fastfetch?
|
||||
### Q: I have my own ASCII art / image file. How can I show it with fastfetch?
|
||||
|
||||
Try `fastfetch -l /path/to/logo`. See [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for detail.
|
||||
Try `fastfetch -l /path/to/logo`. See the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for details.
|
||||
|
||||
If you just want to display distro name in [FIGlet text](https://github.com/pwaller/pyfiglet):
|
||||
If you just want to display the distro name in [FIGlet text](https://github.com/pwaller/pyfiglet):
|
||||
|
||||
```bash
|
||||
# install pyfiglet and jq first
|
||||
@@ -174,38 +174,121 @@ 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?
|
||||
### Q: My image logo behaves strangely. How can I fix it?
|
||||
|
||||
See troubleshooting section: <https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options#troubleshooting>
|
||||
See the troubleshooting section: <https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options#troubleshooting>
|
||||
|
||||
### Q: Fastfetch runs in white and black on shell startup. Why?
|
||||
### Q: Fastfetch runs in black and white on shell startup. Why?
|
||||
|
||||
This issue usually happens when using fastfetch with `p10k`. There are known incompatibility between fastfetch and p10k instant prompt.
|
||||
The p10k doc clearly states that you should NOT print anything to stdout after `p10k-instant-prompt` is initialized. You should either put `fastfetch` before initialization of `p10k-instant-prompt` (recommended)
|
||||
This issue usually occurs when using fastfetch with `p10k`. There are known incompatibilities between fastfetch and p10k instant prompt.
|
||||
The p10k documentation clearly states that you should NOT print anything to stdout after `p10k-instant-prompt` is initialized. You should put `fastfetch` before the initialization of `p10k-instant-prompt` (recommended).
|
||||
|
||||
You can always use `fastfetch --pipe false` to force fastfetch running in colorful mode.
|
||||
You can always use `fastfetch --pipe false` to force fastfetch to run in colorful mode.
|
||||
|
||||
### Q: Why do fastfetch and neofetch show different memory usage result?
|
||||
### Q: Why do fastfetch and neofetch show different memory usage results?
|
||||
|
||||
See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096).
|
||||
|
||||
### Q: Fastfetch shows less dpkg packages than neofetch, is it a bug?
|
||||
### Q: Fastfetch shows fewer 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
|
||||
Neofetch incorrectly counts `rc` packages (packages that have been removed but still have configuration files remaining). See 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?
|
||||
### Q: I use Debian / Ubuntu / Debian-derived distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is this 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`
|
||||
Try upgrading `pci.ids`: Download <https://pci-ids.ucw.cz/v2.2/pci.ids> and overwrite the 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 the 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.
|
||||
Alternatively, you may try using `fastfetch --gpu-driver-specific`, which will make fastfetch attempt to ask the driver for the GPU name if supported.
|
||||
|
||||
### Q: I get the error `Authorization required, but no authorization protocol specified` when running fastfetch as 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>`, where `[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 do I hide a key?
|
||||
|
||||
Set the key to a white space.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"key": " "
|
||||
}
|
||||
```
|
||||
|
||||
### Q: How can I display images on Windows?
|
||||
|
||||
As of April 2025:
|
||||
|
||||
#### mintty and Wezterm
|
||||
|
||||
mintty (used by Bash on Windows and MSYS2) and Wezterm (nightly build only) support the iTerm image protocol on Windows.
|
||||
|
||||
In `config.jsonc`:
|
||||
```json
|
||||
{
|
||||
"logo": {
|
||||
"type": "iterm",
|
||||
"source": "C:/path/to/image.png",
|
||||
"width": <num-in-chars>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Windows Terminal
|
||||
|
||||
Windows Terminal supports the sixel image protocol only.
|
||||
|
||||
* If you installed fastfetch through MSYS2:
|
||||
1. Install imagemagick: `pacman -S mingw-w64-<subsystem>-x86_64-imagemagick`
|
||||
2. In `config.jsonc`:
|
||||
```jsonc
|
||||
{
|
||||
"logo": {
|
||||
"type": "sixel", // DO NOT USE "auto"
|
||||
"source": "C:/path/to/image.png", // Do NOT use `~` as fastfetch is a native Windows program and doesn't apply cygwin path conversion
|
||||
"width": <image-width-in-chars>, // Optional
|
||||
"height": <image-height-in-chars> // Optional
|
||||
}
|
||||
}
|
||||
```
|
||||
* If you installed fastfetch via scoop or downloaded the binary directly from the GitHub Releases page:
|
||||
1. Convert your image manually to sixel format using [any online image conversion service](https://www.google.com/search?q=convert+image+to+sixel)
|
||||
2. In `config.jsonc`:
|
||||
```jsonc
|
||||
{
|
||||
"logo": {
|
||||
"type": "raw", // DO NOT USE "auto"
|
||||
"source": "C:/path/to/image.sixel",
|
||||
"width": <image-width-in-chars>, // Required
|
||||
"height": <image-height-in-chars> // Required
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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:
|
||||
Fastfetch is a system information tool. We only accept hardware or system-level software feature requests. For most personal uses, I recommend using the `Command` module to implement custom functionality, which can be used to grab output from a custom shell script:
|
||||
|
||||
```jsonc
|
||||
// This module shows the default editor
|
||||
@@ -220,23 +303,23 @@ Fastfetch is a system information tool. We only accept hardware or system level
|
||||
}
|
||||
```
|
||||
|
||||
Otherwise, open a feature request in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues).
|
||||
Otherwise, please open a feature request in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues).
|
||||
|
||||
### Q: I have questions. Where can I get help?
|
||||
|
||||
* 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.
|
||||
* For possible bugs, please open an issue in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues). Be sure to fill out the bug report template carefully to help developers investigate.
|
||||
|
||||
## Donate
|
||||
|
||||
If you find Fastfetch to be useful, please consider donating.
|
||||
If you find Fastfetch 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!
|
||||
Give us a star to show your support!
|
||||
|
||||
<a href="https://star-history.com/#fastfetch-cli/fastfetch&Date">
|
||||
<picture>
|
||||
|
||||
+119
-428
@@ -1,430 +1,121 @@
|
||||
__fastfetch_complete_help()
|
||||
{
|
||||
local __ff_helps=(
|
||||
"color"
|
||||
"format"
|
||||
"config"
|
||||
"os-format"
|
||||
"host-format"
|
||||
"kernel-format"
|
||||
"uptime-format"
|
||||
"processes-format"
|
||||
"packages-format"
|
||||
"shell-format"
|
||||
"display-format"
|
||||
"de-format"
|
||||
"wm-format"
|
||||
"wmtheme-format"
|
||||
"theme-format"
|
||||
"icons-format"
|
||||
"font-format"
|
||||
"cursor-format"
|
||||
"terminal-format"
|
||||
"terminalfont-format"
|
||||
"cpu-format"
|
||||
"cpuusage-format"
|
||||
"gpu-format"
|
||||
"memory-format"
|
||||
"swap-format"
|
||||
"disk-format"
|
||||
"battery-format"
|
||||
"poweradapter-format"
|
||||
"locale-format"
|
||||
"localip-format"
|
||||
"publicip-format"
|
||||
"player-format"
|
||||
"media-format"
|
||||
"datetime-format"
|
||||
"date-format"
|
||||
"time-format"
|
||||
"vulkan-format"
|
||||
"opengl-format"
|
||||
"opencl-format"
|
||||
"bluetooth-format"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_helps[*]}" -- "$CURRENT_WORD"))
|
||||
#!/usr/bin/env bash
|
||||
|
||||
_fastfetch() {
|
||||
# Use Bash built-in variables directly
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
|
||||
# Check if Python is available
|
||||
if ! command -v python3 &>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Handle standard completion cases
|
||||
case "$prev" in
|
||||
--color|--color-keys|--color-title|--color-output|--color-separator|--*-color|--*-key-color|--*-output-color|--logo-color-[1-9]|--percent-color-*|--temp-color-*)
|
||||
local -a colors=("black" "red" "green" "yellow" "blue" "magenta" "cyan" "white" "default")
|
||||
COMPREPLY=($(compgen -W "${colors[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--logo|-l)
|
||||
local -a logos
|
||||
readarray -t logos < <(fastfetch --list-logos autocompletion 2>/dev/null)
|
||||
logos+=("none" "small")
|
||||
COMPREPLY=($(compgen -W "${logos[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--config|-c)
|
||||
local -a presets
|
||||
readarray -t presets < <(fastfetch --list-presets autocompletion 2>/dev/null)
|
||||
presets+=("none")
|
||||
COMPREPLY=($(compgen -W "${presets[*]}" -- "$cur"))
|
||||
# Also allow file path completion
|
||||
if type _filedir &>/dev/null; then
|
||||
_filedir
|
||||
elif type compgen &>/dev/null; then
|
||||
COMPREPLY+=($(compgen -f -- "$cur"))
|
||||
fi
|
||||
return
|
||||
;;
|
||||
--structure|-s)
|
||||
# Get all module names in lowercase only
|
||||
local -a structures
|
||||
readarray -t structures < <(fastfetch --list-modules autocompletion 2>/dev/null | cut -d':' -f1 | tr '[:upper:]' '[:lower:]')
|
||||
COMPREPLY=($(compgen -W "${structures[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--help|-h)
|
||||
local -a modules
|
||||
readarray -t modules < <(fastfetch --list-modules autocompletion 2>/dev/null)
|
||||
# Convert to lowercase and keep only module names
|
||||
local -a module_names=()
|
||||
for module in "${modules[@]}"; do
|
||||
module_names+=($(echo "$module" | cut -d':' -f1 | tr '[:upper:]' '[:lower:]')-format)
|
||||
done
|
||||
module_names+=("format" "color")
|
||||
COMPREPLY=($(compgen -W "${module_names[*]}" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--format)
|
||||
COMPREPLY=($(compgen -W "json default" -- "$cur"))
|
||||
return
|
||||
;;
|
||||
--*-format)
|
||||
# Format string completion, handle spaces
|
||||
return
|
||||
;;
|
||||
--*path*|--*file*|--gen-config*|--*data*)
|
||||
# File path completion
|
||||
if type _filedir &>/dev/null; then
|
||||
_filedir
|
||||
elif type compgen &>/dev/null; then
|
||||
COMPREPLY=($(compgen -f -- "$cur"))
|
||||
fi
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
# If not a special option, generate all possible options
|
||||
if [[ "$cur" == -* ]]; then
|
||||
local -a opts
|
||||
readarray -t opts < <(python3 - "$cur" <<'EOF'
|
||||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
def main(current):
|
||||
try:
|
||||
# Use fastfetch --help-raw to get option data
|
||||
output = subprocess.check_output(['fastfetch', '--help-raw'], stderr=subprocess.DEVNULL)
|
||||
data = json.loads(output)
|
||||
|
||||
for category in data.values():
|
||||
for flag in category:
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
if "short" in flag:
|
||||
print(f"-{flag['short']}")
|
||||
|
||||
if "long" in flag:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
for i in range(1, 10):
|
||||
print(f"--logo-color-{i}")
|
||||
else:
|
||||
print(f"--{flag['long']}")
|
||||
except Exception:
|
||||
# If error occurs, return no options
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1])
|
||||
EOF
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${opts[*]}" -- "$cur"))
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
__fastfetch_complete_bool()
|
||||
{
|
||||
COMPREPLY=($(compgen -W "true false" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_string()
|
||||
{
|
||||
if [[ $CURRENT_WORD != "" ]]; then
|
||||
COMPREPLY=("$CURRENT_WORD")
|
||||
fi
|
||||
}
|
||||
|
||||
__fastfetch_complete_path()
|
||||
{
|
||||
COMPREPLY=($(compgen -A file -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_logo()
|
||||
{
|
||||
COMPREPLY=($(compgen -W "$(fastfetch --list-logos autocompletion)" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_logo_type()
|
||||
{
|
||||
local __ff_logo_types=(
|
||||
"auto"
|
||||
"builtin"
|
||||
"file"
|
||||
"raw"
|
||||
"sixel"
|
||||
"kitty"
|
||||
"chafa"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_logo_types[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_binary_prefix()
|
||||
{
|
||||
local __ff_size_binary_prefixes=(
|
||||
"iec"
|
||||
"si"
|
||||
"jedec"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_size_binary_prefixes[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_gl()
|
||||
{
|
||||
local __ff_gl_types=(
|
||||
"auto"
|
||||
"egl"
|
||||
"glx"
|
||||
"osmesa"
|
||||
)
|
||||
COMPREPLY=($(compgen -W "${__ff_gl_types[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_complete_option()
|
||||
{
|
||||
local FF_OPTIONS_ALL=(
|
||||
"${FF_OPTIONS_BOOL[@]}"
|
||||
"${FF_OPTIONS_STRING[@]}"
|
||||
"${FF_OPTIONS_PATH[@]}"
|
||||
"${FF_OPTIONS_LOGO[@]}"
|
||||
"${FF_OPTIONS_LOGO_TYPE[@]}"
|
||||
"${FF_OPTIONS_BINARY_PREFIX[@]}"
|
||||
"${FF_OPTIONS_OPENGL[@]}"
|
||||
)
|
||||
|
||||
if [[ $WORD_COUND -lt 3 ]]; then
|
||||
FF_OPTIONS_ALL+=(
|
||||
"${FF_OPTIONS_SINGLE[@]}"
|
||||
"${FF_OPTIONS_HELP[@]}"
|
||||
)
|
||||
fi
|
||||
|
||||
for ff_word in ${COMP_WORDS[@]}; do
|
||||
if [[ $ff_word == $CURRENT_WORD ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
FF_OPTIONS_ALL=("${FF_OPTIONS_ALL[@]/$ff_word}")
|
||||
done
|
||||
|
||||
COMPREPLY=($(compgen -W "${FF_OPTIONS_ALL[*]}" -- "$CURRENT_WORD"))
|
||||
}
|
||||
|
||||
__fastfetch_previous_matches()
|
||||
{
|
||||
for ff_option in "$@"; do
|
||||
if [[ $ff_option == "$PREVIOUS_WORD" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
__fastfetch_completion()
|
||||
{
|
||||
local CURRENT_WORD="${COMP_WORDS[$COMP_CWORD]}"
|
||||
local PREVIOUS_WORD="${COMP_WORDS[$COMP_CWORD - 1]}"
|
||||
local WORD_COUND="${#COMP_WORDS[@]}"
|
||||
|
||||
local FF_OPTIONS_SINGLE=(
|
||||
"-v"
|
||||
"--version"
|
||||
"--list-logos"
|
||||
"--list-modules"
|
||||
"--list-presets"
|
||||
"--list-features"
|
||||
"--print-logos"
|
||||
"--print-config-system"
|
||||
"--print-config-user"
|
||||
"--print-structure"
|
||||
"--gen-config"
|
||||
"--gen-config-force"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_HELP=(
|
||||
"-h"
|
||||
"--help"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_BOOL=(
|
||||
"-r"
|
||||
"--show-errors"
|
||||
"--logo-print-remaining"
|
||||
"--multithreading"
|
||||
"--stat"
|
||||
"--allow-slow-operations"
|
||||
"--disable-linewrap"
|
||||
"--hide-cursor"
|
||||
"--cpu-temp"
|
||||
"--gpu-temp"
|
||||
"--battery-temp"
|
||||
"--display-precise-refresh-rate"
|
||||
"--localip-show-ipv4"
|
||||
"--localip-show-ipv6"
|
||||
"--localip-show-flags"
|
||||
"--localip-show-loop"
|
||||
"--localip-show-mtu"
|
||||
"--localip-show-speed"
|
||||
"--localip-name-prefix"
|
||||
"--localip-compact-type"
|
||||
"--escape-bedrock"
|
||||
"--pipe"
|
||||
"--title-fqdn"
|
||||
"--disk-folders"
|
||||
"--disk-show-external"
|
||||
"--disk-show-hidden"
|
||||
"--disk-show-subvolumes"
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--gpu-force-method"
|
||||
"--disk-show-unknown"
|
||||
"--bluetooth-show-disconnected"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_STRING=(
|
||||
"--logo-type"
|
||||
"--logo-padding"
|
||||
"--logo-padding-left"
|
||||
"--logo-padding-right"
|
||||
"--logo-padding-top"
|
||||
"--logo-color-1"
|
||||
"--logo-color-2"
|
||||
"--logo-color-3"
|
||||
"--logo-color-4"
|
||||
"--logo-color-5"
|
||||
"--logo-color-6"
|
||||
"--logo-color-7"
|
||||
"--logo-color-8"
|
||||
"--logo-color-9"
|
||||
"--logo-width"
|
||||
"--logo-height"
|
||||
"--color"
|
||||
"--color-keys"
|
||||
"--color-title"
|
||||
"--display-compact-type"
|
||||
"--separator"
|
||||
"-s"
|
||||
"--structure"
|
||||
"--player-name"
|
||||
"--percent-type"
|
||||
"--publicip-url"
|
||||
"--publicip-timeout"
|
||||
"--weather-output-format"
|
||||
"--weather-timeout"
|
||||
"--os-key"
|
||||
"--os-format"
|
||||
"--os-key-color"
|
||||
"--host-key"
|
||||
"--host-format"
|
||||
"--host-key-color"
|
||||
"--kernel-key"
|
||||
"--kernel-format"
|
||||
"--kernel-key-color"
|
||||
"--uptime-key"
|
||||
"--uptime-format"
|
||||
"--uptime-key-color"
|
||||
"--processes-key"
|
||||
"--processes-format"
|
||||
"--processes-key-color"
|
||||
"--packages-key"
|
||||
"--packages-format"
|
||||
"--packages-key-color"
|
||||
"--shell-key"
|
||||
"--shell-format"
|
||||
"--shell-key-color"
|
||||
"--display-key"
|
||||
"--display-format"
|
||||
"--display-key-color"
|
||||
"--de-key"
|
||||
"--de-format"
|
||||
"--de-key-color"
|
||||
"--wm-key"
|
||||
"--wm-format"
|
||||
"--wm-key-color"
|
||||
"--wmtheme-key"
|
||||
"--wmtheme-format"
|
||||
"--wmtheme-key-color"
|
||||
"--theme-key"
|
||||
"--theme-format"
|
||||
"--theme-key-color"
|
||||
"--icons-key"
|
||||
"--icons-format"
|
||||
"--icons-key-color"
|
||||
"--font-key"
|
||||
"--font-format"
|
||||
"--font-key-color"
|
||||
"--cursor-key"
|
||||
"--cursor-format"
|
||||
"--cursor-key-color"
|
||||
"--terminal-key"
|
||||
"--terminal-format"
|
||||
"--terminal-key-color"
|
||||
"--terminalfont-key"
|
||||
"--terminalfont-format"
|
||||
"--terminalfont-key-color"
|
||||
"--cpu-key"
|
||||
"--cpu-format"
|
||||
"--cpu-key-color"
|
||||
"--cpu-useage-key"
|
||||
"--cpu-useage-format"
|
||||
"--cpu-useage-key-color"
|
||||
"--gpu-key"
|
||||
"--gpu-format"
|
||||
"--gpu-key-color"
|
||||
"--memory-key"
|
||||
"--memory-format"
|
||||
"--memory-key-color"
|
||||
"--swap-key"
|
||||
"--swap-format"
|
||||
"--swap-key-color"
|
||||
"--disk-key"
|
||||
"--disk-format"
|
||||
"--disk-key-color"
|
||||
"--battery-key"
|
||||
"--battery-format"
|
||||
"--battery-key-color"
|
||||
"--poweradapter-key"
|
||||
"--poweradapter-format"
|
||||
"--poweradapter-key-color"
|
||||
"--locale-key"
|
||||
"--locale-format"
|
||||
"--locale-key-color"
|
||||
"--localip-key"
|
||||
"--localip-format"
|
||||
"--localip-key-color"
|
||||
"--publicip-key"
|
||||
"--publicip-format"
|
||||
"--publicip-key-color"
|
||||
"--wifi-key"
|
||||
"--wifi-format"
|
||||
"--wifi-key-color"
|
||||
"--weather-key"
|
||||
"--weather-format"
|
||||
"--weather-key-color"
|
||||
"--player-key"
|
||||
"--player-format"
|
||||
"--player-key-color"
|
||||
"--media-key"
|
||||
"--media-format"
|
||||
"--media-key-color"
|
||||
"--datetime-key"
|
||||
"--datetime-format"
|
||||
"--datetime-key-color"
|
||||
"--date-key"
|
||||
"--date-format"
|
||||
"--date-key-color"
|
||||
"--time-key"
|
||||
"--time-format"
|
||||
"--time-key-color"
|
||||
"--vulkan-key"
|
||||
"--vulkan-format"
|
||||
"--vulkan-key-color"
|
||||
"--opengl-key"
|
||||
"--opengl-format"
|
||||
"--opengl-key-color"
|
||||
"--opencl-key"
|
||||
"--opencl-format"
|
||||
"--opencl-key-color"
|
||||
"--users-key"
|
||||
"--users-format"
|
||||
"--users-key-color"
|
||||
"--users-myself-only"
|
||||
"--bluetooth-key"
|
||||
"--bluetooth-format"
|
||||
"--bluetooth-key-color"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_PATH=(
|
||||
"-c"
|
||||
"--config"
|
||||
"--lib-vulkan"
|
||||
"--lib-wayland"
|
||||
"--lib-xcb-randr"
|
||||
"--lib-xcb"
|
||||
"--lib-xrandr"
|
||||
"--lib-X11"
|
||||
"--lib-gio"
|
||||
"--lib-dconf"
|
||||
"--lib-dbus"
|
||||
"--lib-xfconf"
|
||||
"--lib-sqlite3"
|
||||
"--lib-rpm"
|
||||
"--lib-imagemagick"
|
||||
"--lib-z"
|
||||
"--lib-chafa"
|
||||
"--lib-egl"
|
||||
"--lib-glx"
|
||||
"--lib-osmesa"
|
||||
"--lib-opencl"
|
||||
"--lib-pulse"
|
||||
"--lib-ddcutil"
|
||||
"--lib-nm"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO=(
|
||||
"-l"
|
||||
"--logo"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_LOGO_TYPE=(
|
||||
"--logo-type"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_BINARY_PREFIX=(
|
||||
"--binary-prefix"
|
||||
)
|
||||
|
||||
local FF_OPTIONS_OPENGL=(
|
||||
"--opengl-type"
|
||||
)
|
||||
|
||||
if __fastfetch_previous_matches "${FF_OPTIONS_SINGLE[@]}"; then
|
||||
return
|
||||
elif [[ $WORD_COUND -gt 3 && ( ${COMP_WORDS[$COMP_CWORD - 2]} == "--help" || ${COMP_WORDS[$COMP_CWORD - 2]} == "-h" ) ]]; then
|
||||
return
|
||||
elif [[ $CURRENT_WORD == "-"* ]]; then
|
||||
__fastfetch_complete_option
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_HELP[@]}"; then
|
||||
__fastfetch_complete_help
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_BOOL[@]}"; then
|
||||
__fastfetch_complete_bool
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_STRING[@]}"; then
|
||||
__fastfetch_complete_string
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_PATH[@]}"; then
|
||||
__fastfetch_complete_path
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO[@]}"; then
|
||||
__fastfetch_complete_logo
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_LOGO_TYPE[@]}"; then
|
||||
__fastfetch_complete_logo_type
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_BINARY_PREFIX[@]}"; then
|
||||
__fastfetch_complete_binary_prefix
|
||||
elif __fastfetch_previous_matches "${FF_OPTIONS_OPENGL[@]}"; then
|
||||
__fastfetch_complete_gl
|
||||
else
|
||||
__fastfetch_complete_option
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F __fastfetch_completion fastfetch
|
||||
# Register completion
|
||||
complete -F _fastfetch fastfetch
|
||||
|
||||
@@ -62,11 +62,17 @@ end
|
||||
echo '
|
||||
import json, subprocess, sys
|
||||
|
||||
|
||||
def main():
|
||||
data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"]))
|
||||
|
||||
for key in data:
|
||||
for flag in data[key]:
|
||||
if flag["long"] == "logo-color-[1-9]":
|
||||
for i in range(1, 10):
|
||||
print(f"""complete -c fastfetch -d "{flag["desc"]}" -l "logo-color-{i}" -x -a "(__fastfetch_complete_color)" """)
|
||||
continue
|
||||
|
||||
if flag.get("pseudo", False):
|
||||
continue
|
||||
|
||||
@@ -75,7 +81,7 @@ def main():
|
||||
command_prefix += f""" -o {flag["short"]}"""
|
||||
|
||||
if "arg" in flag:
|
||||
type: str = flag["arg"]["type"];
|
||||
type: str = flag["arg"]["type"]
|
||||
if type == "bool":
|
||||
print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"")
|
||||
elif type == "color":
|
||||
@@ -98,6 +104,7 @@ def main():
|
||||
else:
|
||||
print(f"{command_prefix} -f")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
|
||||
Vendored
+132
@@ -1,3 +1,135 @@
|
||||
fastfetch (2.48.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.48.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 17 Jul 2025 16:16:52 +0800
|
||||
|
||||
fastfetch (2.47.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.47.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 03 Jul 2025 14:51:45 +0800
|
||||
|
||||
fastfetch (2.46.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.46.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 20 Jun 2025 15:01:21 +0800
|
||||
|
||||
fastfetch (2.45.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.45.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 05 Jun 2025 10:56:38 +0800
|
||||
|
||||
fastfetch (2.44.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.44.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 26 May 2025 14:59:01 +0800
|
||||
|
||||
fastfetch (2.43.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.43.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 14 May 2025 09:49:50 +0800
|
||||
|
||||
fastfetch (2.42.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.42.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 30 Apr 2025 14:08:57 +0800
|
||||
|
||||
fastfetch (2.41.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.41.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 16 Apr 2025 13:42:58 +0800
|
||||
|
||||
fastfetch (2.40.4) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.4
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 10 Apr 2025 15:38:21 +0800
|
||||
|
||||
fastfetch (2.40.3) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.3
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 07 Apr 2025 09:29:27 +0800
|
||||
|
||||
fastfetch (2.40.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 03 Apr 2025 08:46:54 +0800
|
||||
|
||||
fastfetch (2.39.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.39.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Fri, 21 Mar 2025 11:02:19 +0800
|
||||
|
||||
fastfetch (2.39.0ubuntu1) jammy; urgency=medium
|
||||
|
||||
* Remove unwanted debugging code
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:39:22 +0800
|
||||
|
||||
fastfetch (2.39.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.39.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 20 Mar 2025 10:35:18 +0800
|
||||
|
||||
fastfetch (2.38.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.38.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 05 Mar 2025 14:56:24 +0800
|
||||
|
||||
fastfetch (2.37.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.37.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 19 Feb 2025 15:43:42 +0800
|
||||
|
||||
fastfetch (2.36.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.36.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Tue, 11 Feb 2025 13:39:55 +0800
|
||||
|
||||
fastfetch (2.36.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.36.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 10 Feb 2025 10:13:53 +0800
|
||||
|
||||
fastfetch (2.35.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.35.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Sun, 26 Jan 2025 10:15:22 +0800
|
||||
|
||||
fastfetch (2.34.1) jammy; urgency=medium
|
||||
|
||||
* Update to 2.34.1
|
||||
|
||||
-- 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
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: fastfetch
|
||||
Section: universe/utils
|
||||
Priority: optional
|
||||
Maintainer: Carter Li <zhangsongcui@live.cn>
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, libosmesa6-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Build-Depends: libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libxfconf-0-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
|
||||
Standards-Version: 4.0.0
|
||||
Homepage: https://github.com/fastfetch-cli/fastfetch
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.32.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.48.0_source.buildinfo universe/utils optional
|
||||
|
||||
+140
-59
@@ -1,8 +1,7 @@
|
||||
.TH FASTFETCH 1 "@FASTFETCH_BUILD_DATE@" "@CMAKE_PROJECT_NAME@ @CMAKE_PROJECT_VERSION@"
|
||||
|
||||
.SH NAME
|
||||
fastfetch \- a neofetch\-like tool for fetching system information and
|
||||
displaying them in a pretty way
|
||||
fastfetch \- a fast and customizable system information tool similar to neofetch
|
||||
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -11,15 +10,12 @@ displaying them in a pretty way
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
Fastfetch is a neofetch\-like tool for fetching system information and
|
||||
displaying them in a pretty way. It is written mainly in C, with performance
|
||||
and customizability in mind.
|
||||
Currently, Linux, Android, FreeBSD, MacOS and Windows 7+ are supported.
|
||||
Fastfetch is a tool for displaying system information in a visually appealing way. Written primarily in C, it focuses on performance and customizability while providing functionality similar to neofetch.
|
||||
It supports Linux, Android, *BSD, macOS, Haiku, and Windows 7 or newer.
|
||||
|
||||
.SH "EXIT STATUS"
|
||||
|
||||
On successful execution, fastfetch returns zero. If any error happened,
|
||||
the exit code will be non\-zero.
|
||||
Fastfetch returns zero on successful execution. Any errors result in a non-zero exit code.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
@@ -27,115 +23,200 @@ the exit code will be non\-zero.
|
||||
.TP
|
||||
|
||||
.B \-h, \-\-help \fI[command]
|
||||
Show help output, displaying all available options or help for given command
|
||||
Display help information for all available options or for a specific command
|
||||
.TP
|
||||
|
||||
.B \-v, \-\-version
|
||||
Show version of fastfetch
|
||||
Display the version of fastfetch
|
||||
.TP
|
||||
|
||||
.B \-\-version\-raw
|
||||
Display the raw version string (major.minor.patch)
|
||||
.TP
|
||||
|
||||
.B \-\-list\-config\-paths
|
||||
List search paths of config files
|
||||
List search paths for configuration files
|
||||
.TP
|
||||
|
||||
.B \-\-list\-data\-paths
|
||||
List search paths of presets and logos
|
||||
List search paths for presets and logos
|
||||
.TP
|
||||
|
||||
.B \-\-list\-logos
|
||||
List available logos, they can be loaded with \fI\-\-logo
|
||||
List available logos that can be loaded with \fI\-\-logo
|
||||
.TP
|
||||
|
||||
.B \-\-list\-modules
|
||||
List available modules
|
||||
List all available modules
|
||||
.TP
|
||||
|
||||
.B \-\-list\-presets
|
||||
List available presets, they can be loaded with \fI\-\-config
|
||||
List available presets that can be loaded with \fI\-\-config
|
||||
.TP
|
||||
|
||||
.B \-\-list\-features
|
||||
List the supported features fastfetch was compiled with
|
||||
List the features that fastfetch was compiled with (mainly for development)
|
||||
.TP
|
||||
|
||||
.B \-\-print\-logos
|
||||
Print available logos
|
||||
Display all available logos
|
||||
.TP
|
||||
|
||||
.B \-\-print\-structure
|
||||
Print the default structure
|
||||
Display the default structure
|
||||
.TP
|
||||
|
||||
.B \-\-format \fI<type>
|
||||
Set the output format. Besides the
|
||||
.I default
|
||||
format, only
|
||||
.I json
|
||||
is supported currently.
|
||||
|
||||
|
||||
.SS "Display Options"
|
||||
.TP
|
||||
|
||||
.B \-l, \-\-logo \fI<logo>
|
||||
Set the logo to display
|
||||
.TP
|
||||
|
||||
.B \-s, \-\-structure \fI<structure>
|
||||
Set the structure of the fetch. For details about the structure,
|
||||
see the CONFIGURATION section.
|
||||
|
||||
Set the output format. Available options are:
|
||||
.RS
|
||||
.IP \(bu 2
|
||||
\fIdefault\fR: Default human-readable format
|
||||
.IP \(bu 2
|
||||
\fIjson\fR: JSON format for machine processing
|
||||
.RE
|
||||
|
||||
.SS "Config Options"
|
||||
.TP
|
||||
|
||||
.B \-c, \-\-config \fI<config>
|
||||
Use the specified config file or preset. If
|
||||
.I none
|
||||
is specified, disable further config loading. For details about
|
||||
config files, see the CONFIGURATION section
|
||||
Use the specified config file or preset. Specify \fInone\fR to disable further config loading. See the CONFIGURATION section for details on config files.
|
||||
.TP
|
||||
|
||||
.B \-\-gen\-config \fI[file]
|
||||
Generate a config file with options specified on the command line.
|
||||
If \fIfile\fR is specified, the configuration will be written to the
|
||||
file, otherwise it will be written to stdout.
|
||||
.B \-\-gen\-config \fI[path]
|
||||
Generate a config file with options specified on the command line. If \fIpath\fR is not specified, it defaults to \fB~/.config/fastfetch/config.jsonc\fR. If \fIpath\fR is "\-", the configuration will be written to stdout.
|
||||
.TP
|
||||
|
||||
.B \-\-gen\-config\-force \fI[file]
|
||||
Same as \fB\-\-gen\-config\fR, but overwrites existing config
|
||||
.B \-\-gen\-config\-force \fI[path]
|
||||
Same as \fB\-\-gen\-config\fR, but overwrites any existing file at the destination path.
|
||||
.TP
|
||||
|
||||
.SS "Logo Options"
|
||||
.TP
|
||||
|
||||
To list all options, use \fB\-\-help\fR. It will also print all available module options.
|
||||
.B \-l, \-\-logo \fI<logo>
|
||||
Set the logo to display. Can be the name of a built-in logo or a path to an image file. Use \fInone\fR to disable the logo.
|
||||
.TP
|
||||
|
||||
.B \-\-logo\-type \fI<type>
|
||||
Set the type of the logo specified with \fI\-\-logo\fR. Available types include \fIauto\fR, \fIbuiltin\fR, \fIfile\fR, \fIsixel\fR, \fIkitty\fR, and others. See \fB\-\-help logo\-type\fR for details.
|
||||
.TP
|
||||
|
||||
.B \-\-logo\-width \fI<width>
|
||||
Set the width of the logo in characters (for image logos)
|
||||
.TP
|
||||
|
||||
.B \-\-logo\-height \fI<height>
|
||||
Set the height of the logo in characters (for image logos)
|
||||
.TP
|
||||
|
||||
.B \-\-logo\-color\-[1\-9] \fI<color>
|
||||
Override specific colors in the logo
|
||||
|
||||
.SS "Display Options"
|
||||
.TP
|
||||
|
||||
.B \-s, \-\-structure \fI<structure>
|
||||
Set the structure of the fetch (a colon-separated list of module names)
|
||||
.TP
|
||||
|
||||
.B \-\-color \fI<color>
|
||||
Set the color of keys and title. See \fB\-\-help color\fR for available colors.
|
||||
.TP
|
||||
|
||||
.B \-\-color\-keys \fI<color>
|
||||
Set the color of keys only
|
||||
.TP
|
||||
|
||||
.B \-\-color\-title \fI<color>
|
||||
Set the color of the title only
|
||||
.TP
|
||||
|
||||
.B \-\-separator \fI<string>
|
||||
Set the separator between key and value (default: ": ")
|
||||
.TP
|
||||
|
||||
.B \-\-key\-width \fI<num>
|
||||
Align the width of keys to \fI<num>\fR characters
|
||||
.TP
|
||||
|
||||
.B \-\-show\-errors
|
||||
Display errors when they occur (default: false)
|
||||
.TP
|
||||
|
||||
.B \-\-pipe
|
||||
Disable colors (automatically detected based on whether stdout is a terminal)
|
||||
|
||||
To list all available options including module-specific options, use \fB\-\-help\fR.
|
||||
|
||||
.SH CONFIGURATION
|
||||
.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 (:).
|
||||
The structure defines which modules to display and in what order. It consists of module names separated by colons (:).
|
||||
For example: \fBtitle:separator:os:kernel:uptime\fR
|
||||
|
||||
To list all available modules, use \fB\-\-list\-modules\fR
|
||||
|
||||
.SS "Config Files"
|
||||
|
||||
Fastfetch uses JSONC based format for configuration. Fastfetch doesn't generate
|
||||
config file automatically; it should be generated manually by \fB\-\-gen\-config\fR.
|
||||
The config file will be saved in \fB~/.config/fastfetch/config.jsonc\fR by default.
|
||||
Fastfetch uses JSONC for configuration files. JSONC is JSON with support for comments (// and /* */). Configuration files must have the .jsonc extension.
|
||||
|
||||
A JSONC config file is a JSON file that also supports comments with (// and /* */).
|
||||
Those files must have the extension '.jsonc'.
|
||||
You can generate a default config file using \fB\-\-gen\-config\fR. By default, the config file is saved at \fB~/.config/fastfetch/config.jsonc\fR.
|
||||
|
||||
The specified configuration/preset files are searched in the following order:
|
||||
The configuration/preset files are searched in the following locations (in order):
|
||||
|
||||
1. relative to the current working directory
|
||||
.RS
|
||||
.IP 1. 4
|
||||
Relative to the current working directory
|
||||
.IP 2. 4
|
||||
Relative to ~/.local/share/fastfetch/presets/
|
||||
.IP 3. 4
|
||||
Relative to /usr/share/fastfetch/presets/
|
||||
.RE
|
||||
|
||||
2. relative to ~/.local/share/fastfetch/presets/
|
||||
For detailed information on logo options, module configuration, and formatting, visit:
|
||||
.RS
|
||||
\fIhttps://github.com/fastfetch-cli/fastfetch/wiki/Configuration\fR
|
||||
.RE
|
||||
|
||||
3. relative to /usr/share/fastfetch/presets/
|
||||
Fastfetch provides several built-in presets. List them with \fB\-\-list\-presets\fR.
|
||||
|
||||
Fastfetch provides some default presets. List them with \fB\-\-list\-presets\fR.
|
||||
.SS "JSON Schema"
|
||||
A JSON schema is available for editor intelligence when editing the configuration file. Add the following line at the beginning of your config file:
|
||||
.PP
|
||||
\fB"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json"\fR
|
||||
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
Basic usage:
|
||||
.RS
|
||||
\fBfastfetch\fR
|
||||
.RE
|
||||
.TP
|
||||
Use a specific logo:
|
||||
.RS
|
||||
\fBfastfetch \-\-logo arch\fR
|
||||
.RE
|
||||
.TP
|
||||
Custom structure:
|
||||
.RS
|
||||
\fBfastfetch \-\-structure title:os:kernel:uptime:memory\fR
|
||||
.RE
|
||||
.TP
|
||||
Generate a config file:
|
||||
.RS
|
||||
\fBfastfetch \-\-gen\-config\fR
|
||||
.RE
|
||||
.TP
|
||||
Use a preset:
|
||||
.RS
|
||||
\fBfastfetch \-\-config neofetch\fR
|
||||
.RE
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR neofetch (1)
|
||||
|
||||
.SH BUGS
|
||||
Please report bugs to: \fIhttps://github.com/fastfetch\-cli/fastfetch/issues\fR
|
||||
|
||||
.SH AUTHORS
|
||||
Fastfetch is developed by a team of contributors on GitHub.
|
||||
Visit \fIhttps://github.com/fastfetch-cli/fastfetch\fR for more information.
|
||||
|
||||
+562
-125
File diff suppressed because it is too large
Load Diff
+6
-1
@@ -52,7 +52,10 @@
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
{
|
||||
"type": "swap",
|
||||
"separate": true
|
||||
},
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
@@ -90,6 +93,8 @@
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
|
||||
+6
-1
@@ -54,7 +54,10 @@
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
{
|
||||
"type": "swap",
|
||||
"separate": true
|
||||
},
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
@@ -92,6 +95,8 @@
|
||||
"sound",
|
||||
"camera",
|
||||
"gamepad",
|
||||
"mouse",
|
||||
"keyboard",
|
||||
{
|
||||
"type": "weather",
|
||||
"timeout": 1000
|
||||
|
||||
@@ -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",
|
||||
|
||||
+11
-11
@@ -28,38 +28,38 @@
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}{$1}│ {#92}User {#90}│",
|
||||
"format": "{$2}{$3}{user-name} {#2}[{home-dir}]"
|
||||
"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}]",
|
||||
"format": "{$2}{$3}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} [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}]"
|
||||
"format": "{$2}{$3}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} [{weekday}] [W{week}] [UTC{offset-from-utc}]"
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}{$1}│ {#93}Host: {#90}│",
|
||||
"format": "{$2}{$3}{#1}{#36}{host-name}"
|
||||
"key": "{#90}{$1}│ {#93}Host {#90}│",
|
||||
"format": "{$2}{$3}{host-name}"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": "{#90}{$1}│ {#93}Machine {#90}│",
|
||||
"format": "{$2}{$3}{name} {#2}{version}"
|
||||
"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}]"
|
||||
"format": "{$2}{$3}{?pretty-name}{pretty-name}{?}{/pretty-name}{name}{/} {codename} {#2}[v{version}] [{arch}]"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "{#90}{$1}│ {#93}Kernel {#90}│",
|
||||
"format": "{$2}{$3}{sysname} {#2}[v{release}]"
|
||||
"format": "{$2}{$3}{sysname} {#2}[v{release}]"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
@@ -71,14 +71,14 @@
|
||||
"key": "{#90}{$1}│ {#91}CPU {#90}│",
|
||||
"showPeCoreCount": true,
|
||||
"temp": true,
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-types}] {#2}[{freq-max}]"
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-types}] [{freq-max}]"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "{#90}{$1}│ {#91}GPU {#90}│",
|
||||
"detectionMethod": "auto",
|
||||
"driverSpecific": true,
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-count}] {#2}[{type}]"
|
||||
"format": "{$2}{$3}{name} {#2}[C:{core-count}]{?frequency} [{frequency}]{?} [{type}]"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
@@ -98,7 +98,7 @@
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "{#90}{$1}│ {#95}Terminal {#90}│",
|
||||
"format": "{$2}{$3}{pretty-name} {#2}[{version}] [PID:{pid}]"
|
||||
"format": "{$2}{$3}{pretty-name} {#2}[{version}] [PID:{pid}]"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
// Based on #1576
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"display": {
|
||||
"color": {
|
||||
"keys": "blue"
|
||||
},
|
||||
"separator": "",
|
||||
"constants": [
|
||||
"──────────────────────────────────────────────",
|
||||
"\u001b[47D",
|
||||
"\u001b[47C",
|
||||
"\u001b[46C"
|
||||
],
|
||||
"brightColor": false
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"type": "version",
|
||||
"key": "┌───────────────┬─{$1}┐\u001b[41D",
|
||||
"format": "\u001b[1m{#keys} {1} - {2} "
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "│ {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "│ {icon} Fetched │{$3}│{$2}",
|
||||
"format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {timezone-name}"
|
||||
},
|
||||
{
|
||||
"type": "locale",
|
||||
"key": "│ {icon} Locale │{$3}│{$2}"
|
||||
},
|
||||
|
||||
// Hardware
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_cyan} Hardware "
|
||||
},
|
||||
{
|
||||
"type": "chassis",
|
||||
"key": "│{#cyan}│ {icon} Chassis │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "│{#cyan}│ {icon} RAM │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "swap",
|
||||
"key": "│{#cyan}│ {icon} SWAP │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "│{#cyan}│ {icon} CPU │{$4}│{#keys}│{$2}",
|
||||
"showPeCoreCount": true
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#cyan}│ {icon} GPU │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "│{#cyan}│ {icon} Disk │{$4}│{#keys}│{$2}",
|
||||
"format": "{size-used} \/ {size-total} ({size-percentage}) - {filesystem}",
|
||||
},
|
||||
{
|
||||
"type": "battery",
|
||||
"key": "│{#cyan}│ {icon} Battery │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#cyan}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Desktop
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_green} Desktop "
|
||||
},
|
||||
{
|
||||
"type": "de",
|
||||
"key": "│{#green}│ {icon} Desktop │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "wm",
|
||||
"key": "│{#green}│ {icon} Session │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "display",
|
||||
"key": "│{#green}│ {icon} Display │{$4}│{#keys}│{$2}",
|
||||
"compactType": "original-with-refresh-rate"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "│{#green}│ {icon} G-Driver │{$4}│{#keys}│{$2}",
|
||||
"format": "{driver}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#green}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Terminal
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}┌──────────────┬{$1}┐{#keys}│\u001b[37D",
|
||||
"format": "{#bright_yellow} Terminal "
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "│{#yellow}│ {icon} Shell │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "│{#yellow}│ {icon} Terminal │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "│{#yellow}│ {icon} Term Font │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "terminaltheme",
|
||||
"key": "│{#yellow}│ {icon} Colors │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "│{#yellow}│ {icon} Packages │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#yellow}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Development
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}┌──────────────┬{$1}┐{#keys}│\u001b[39D",
|
||||
"format": "{#bright_red} Development "
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Rust │{$4}│{#keys}│{$2}",
|
||||
"text": "rustc --version | cut -d' ' -f2",
|
||||
"format": "rustc {}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Clang │{$4}│{#keys}│{$2}",
|
||||
"text": "clang --version | head -1 | awk '{print $NF}'",
|
||||
"format": "clang {}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} NodeJS │{$4}│{#keys}│{$2}",
|
||||
"text": "node --version",
|
||||
"format": "node {~1}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Go │{$4}│{#keys}│{$2}",
|
||||
"text": "go version | cut -d' ' -f3",
|
||||
"format": "go {~2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Zig │{$4}│{#keys}│{$2}",
|
||||
"text": "zig version",
|
||||
"format": "zig {}"
|
||||
},
|
||||
{
|
||||
"type": "editor",
|
||||
"key": "│{#red}│ {icon} Editor │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"keyIcon": "",
|
||||
"key": "│{#red}│ {icon} Git │{$4}│{#keys}│{$2}",
|
||||
"text": "git version",
|
||||
"format": "git {~12}"
|
||||
},
|
||||
{
|
||||
"type": "font",
|
||||
"key": "│{#red}│ {icon} Interface │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#red}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// Uptime
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}┌──────────────┬{$1}┐{#keys}│\u001b[36D",
|
||||
"format": "{#bright_magenta} Uptime "
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "│{#magenta}│ {icon} Uptime │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"myselfOnly": true,
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} Login │{$4}│{#keys}│{$2}"
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"!system": "macOS"
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"folders": "/",
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"condition": {
|
||||
"system": "macOS"
|
||||
},
|
||||
"type": "disk",
|
||||
"keyIcon": "",
|
||||
"key": "│{#magenta}│ {icon} OS Age │{$4}│{#keys}│{$2}",
|
||||
"folders": "/System/Volumes/VM",
|
||||
"format": "{create-time:10} [{days} days]"
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "│{#magenta}└──────────────┴{$1}┘{#keys}│",
|
||||
"format": ""
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "└─────────────────{$1}┘",
|
||||
"format": ""
|
||||
},
|
||||
|
||||
// End
|
||||
"break",
|
||||
"colors"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
// Modified from: 24.jsonc
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"padding": {
|
||||
"top": 2
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": "",
|
||||
"constants": [
|
||||
// CONSTANT {$1} - 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}╭ Keys ───────╮",
|
||||
"format": "{#90}╭ Values ────────────────────────────────────────────────────╮",
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}│ {#92}User {#90}│",
|
||||
"format": "{$1}{user-name} {#2}[{home-dir}]"
|
||||
},
|
||||
{
|
||||
"type": "users",
|
||||
"key": "{#90}│ {#92}Users {#90}│",
|
||||
"myselfOnly": false,
|
||||
"format": "{$1}{1}@{host-name}{/host-name}localhost{/}{?client-ip} {#2}[IP:{client-ip}]{?} [Login time: {login-time}]"
|
||||
},
|
||||
{
|
||||
"type": "datetime",
|
||||
"key": "{#90}│ {#92}Datetime {#90}│",
|
||||
"format": "{$1}{year}-{month-pretty}-{day-in-month} {hour-pretty}:{minute-pretty}:{second-pretty} {#2}[{weekday}] [W{week}] [UTC{offset-from-utc}]"
|
||||
},
|
||||
{
|
||||
"type": "title",
|
||||
"key": "{#90}│ {#93}Host {#90}│",
|
||||
"format": "{$1}{host-name}"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"key": "{#90}│ {#93}Machine {#90}│",
|
||||
"format": "{$1}{name} {#2}{version}"
|
||||
},
|
||||
{
|
||||
"type": "os",
|
||||
"key": "{#90}│ {#93}OS {#90}│",
|
||||
"format": "{$1}{?pretty-name}{pretty-name}{?}{/pretty-name}{name}{/} {codename} {#2}[v{version}] [{arch}]"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "{#90}│ {#93}Kernel {#90}│",
|
||||
"format": "{$1}{sysname} {#2}[v{release}]"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"key": "{#90}│ {#93}Uptime {#90}│",
|
||||
"format": "{$1}{?days}{days} Days + {?}{hours}:{minutes}:{seconds}"
|
||||
},
|
||||
{
|
||||
"type": "cpu",
|
||||
"key": "{#90}│ {#91}CPU {#90}│",
|
||||
"showPeCoreCount": true,
|
||||
"temp": true,
|
||||
"format": "{$1}{name} {#2}[C:{core-types}] [{freq-max}]"
|
||||
},
|
||||
{
|
||||
"type": "gpu",
|
||||
"key": "{#90}│ {#91}GPU {#90}│",
|
||||
"detectionMethod": "auto",
|
||||
"driverSpecific": true,
|
||||
"format": "{$1}{name} {#2}[C:{core-count}]{?frequency} [{frequency}]{?} {#2}[{type}]"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "{#90}│ {#91}Memory {#90}│",
|
||||
"format": "{$1}{used} / {total} ({percentage})"
|
||||
},
|
||||
{
|
||||
"type": "disk",
|
||||
"key": "{#90}│ {#91}Disk {#90}│",
|
||||
"format": "{$1}{size-used} / {size-total} ({size-percentage})"
|
||||
},
|
||||
{
|
||||
"type": "poweradapter",
|
||||
"key": "{#90}│ {#91}Power {#90}│",
|
||||
"format": "{$1}{name}"
|
||||
},
|
||||
{
|
||||
"type": "terminal",
|
||||
"key": "{#90}│ {#95}Terminal {#90}│",
|
||||
"format": "{$1}{pretty-name} {#2}[{version}] [PID:{pid}]"
|
||||
},
|
||||
{
|
||||
"type": "terminalfont",
|
||||
"key": "{#90}│ {#95}Font {#90}│",
|
||||
"format": "{$1}{name} {#2}[{size}]"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"key": "{#90}│ {#95}Shell {#90}│",
|
||||
"format": "{$1}{pretty-name} {#2}[v{version}] [PID:{pid}]"
|
||||
},
|
||||
{
|
||||
// localip IPv4
|
||||
"type": "localip",
|
||||
"key": "{#90}│ {#94}Local IPv4 {#90}│",
|
||||
"showPrefixLen": true,
|
||||
"showIpv4": true,
|
||||
"showIpv6": false,
|
||||
"showMtu": true,
|
||||
"format": "{$1}{ifname}: {ipv4} {#2}[MTU:{mtu}]"
|
||||
},
|
||||
{
|
||||
// localip IPv6
|
||||
"type": "localip",
|
||||
"key": "{#90}│ {#94}Local IPv6 {#90}│",
|
||||
"showPrefixLen": true,
|
||||
"showIpv4": false,
|
||||
"showIpv6": true,
|
||||
"showMtu": true,
|
||||
"format": "{$1}{ifname}: {ipv6} {#2}[MTU:{mtu}]"
|
||||
},
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "{#90}│ {#94}Public IPv4 {#90}│",
|
||||
"ipv6": false,
|
||||
"format": "{$1}{ip} {#2}[{location}]"
|
||||
},
|
||||
{
|
||||
"type": "publicip",
|
||||
"key": "{#90}│ {#94}Public IPv6 {#90}│",
|
||||
"ipv6": true,
|
||||
"format": "{$1}{ip} {#2}[{location}]"
|
||||
},
|
||||
// CUSTOM - Button UI bar
|
||||
{
|
||||
"type": "custom",
|
||||
"key": "{#90}╰─────────────╯",
|
||||
"format": "{#90}╰────────────────────────────────────────────────────────────╯",
|
||||
},
|
||||
"break",
|
||||
{
|
||||
"type": "custom",
|
||||
"key": " ",
|
||||
"format": "{#90}╭ Colors ───────────────────────────────────────────────────────────────────╮",
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "{#90}│ {#40} {#41} {#42} {#43} {#44} {#45} {#46} {#47} {#} {#90}│",
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "{#90}│ {#100} {#101} {#102} {#103} {#104} {#105} {#106} {#107} {#} {#90}│",
|
||||
},
|
||||
{
|
||||
"type": "custom",
|
||||
"format": "{#90}╰───────────────────────────────────────────────────────────────────────────╯",
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {
|
||||
"type": "small",
|
||||
"padding": {
|
||||
"top": 1
|
||||
}
|
||||
},
|
||||
"display": {
|
||||
"separator": " "
|
||||
},
|
||||
"modules": [
|
||||
"break",
|
||||
"title",
|
||||
{
|
||||
"type": "os",
|
||||
"key": "os ",
|
||||
"keyColor": "red"
|
||||
},
|
||||
{
|
||||
"type": "kernel",
|
||||
"key": "kernel",
|
||||
"keyColor": "green"
|
||||
},
|
||||
{
|
||||
"type": "host",
|
||||
"format": "{vendor} {family}",
|
||||
"key": "host ",
|
||||
"keyColor": "yellow"
|
||||
},
|
||||
{
|
||||
"type": "packages",
|
||||
"key": "pkgs ",
|
||||
"keyColor": "blue"
|
||||
},
|
||||
{
|
||||
"type": "uptime",
|
||||
"format": "{?days}{days}d {?}{hours}h {minutes}m",
|
||||
"key": "uptime",
|
||||
"keyColor": "magenta"
|
||||
},
|
||||
{
|
||||
"type": "memory",
|
||||
"key": "memory",
|
||||
"keyColor": "cyan"
|
||||
},
|
||||
"break"
|
||||
]
|
||||
}
|
||||
@@ -16,7 +16,10 @@
|
||||
"format": "{release}"
|
||||
},
|
||||
"uptime",
|
||||
"packages",
|
||||
{
|
||||
"type": "packages",
|
||||
"combined": true
|
||||
},
|
||||
"shell",
|
||||
{
|
||||
"type": "display",
|
||||
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
def main(amdgpu_ids_path: str):
|
||||
with open(amdgpu_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
products = []
|
||||
for line in full_text.split('\n'):
|
||||
if not line or line[0] == '#' or not ',\t' in line:
|
||||
continue
|
||||
device, revision, name = line.split(',\t', maxsplit=2)
|
||||
products.append((device, revision, name))
|
||||
|
||||
code = """\
|
||||
// SPDX-License-Identifier: MIT
|
||||
// https://opensource.org/license/mit
|
||||
// Generated from https://gitlab.freedesktop.org/mesa/drm/-/raw/main/data/amdgpu.ids
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct FFArmGpuProduct
|
||||
{
|
||||
const uint32_t id; // device << 8 | revision
|
||||
const char* name;
|
||||
} FFArmGpuProduct;
|
||||
|
||||
const FFArmGpuProduct ffAmdGpuProducts[] = {
|
||||
"""
|
||||
|
||||
for device, revision, name in products:
|
||||
code += f" {{ 0x{device} << 8 | 0x{revision}, \"{name}\" }},\n"
|
||||
|
||||
code += "};\n"
|
||||
|
||||
print(code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
len(sys.argv) == 2 or sys.exit('Usage: gen-amdgpuids.py </path/to/amdgpu.ids>')
|
||||
|
||||
main(sys.argv[1])
|
||||
+121
-52
@@ -1,11 +1,15 @@
|
||||
#!/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
|
||||
Python script to generate a comprehensive man page for the command `fastfetch`.
|
||||
|
||||
The generated man page content will be printed to stdout,
|
||||
so you will need to pipe it to a file if you want to save it.
|
||||
Example: python3 gen-man.py > fastfetch.1
|
||||
|
||||
The command options are generated using a JSON file.
|
||||
For the JSON file format, see:
|
||||
https://github.com/fastfetch-cli/fastfetch/blob/dev/src/data/help.json
|
||||
"""
|
||||
|
||||
from json import load
|
||||
@@ -33,7 +37,7 @@ pathToHelpFile = path.join(pathToCurrentDir, "../src/data/help.json")
|
||||
# man page section
|
||||
manSection = 1
|
||||
# title (center header)
|
||||
titlePage = "Fastfetch man page"
|
||||
titlePage = "FASTFETCH"
|
||||
# date (center footer)
|
||||
# format : "Month (abbreviation) Day Year"
|
||||
todayDate = datetime.fromtimestamp(
|
||||
@@ -47,81 +51,118 @@ 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"
|
||||
nameSection = r"fastfetch \- A fast and feature-rich system information tool similar to neofetch"
|
||||
|
||||
# text displayed in the "DESCRIPTION" section
|
||||
descriptionSection = r"""
|
||||
Fastfetch is a tool for displaying system information in a visually appealing way. Written primarily in C, it focuses on performance and customizability while providing functionality similar to neofetch.
|
||||
It supports Linux, Android, FreeBSD, macOS, and Windows 7 or newer.
|
||||
"""
|
||||
|
||||
# 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.
|
||||
Options are parsed in a case-insensitive manner. For example, \fB--logo-type\fR and \fB--LOGO-TYPE\fR are treated identically.
|
||||
|
||||
If a value is between square brackets, it is optional.
|
||||
An optional boolean value defaults to true if not specified.
|
||||
Arguments in square brackets are optional. Optional boolean arguments default to 'true' when specified without a value.
|
||||
|
||||
More detailed help messages for each options can be printed
|
||||
with \fB-h <option_without_dash_prefix>\fR.
|
||||
For more detailed information about a specific option, use:
|
||||
\fBfastfetch -h <option_name_without_dashes>\fR
|
||||
|
||||
All options can be made permanent with command
|
||||
\fBfastfetch <options> --gen-config\fR.
|
||||
Any combination of options can be made permanent by generating a configuration file:
|
||||
\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.
|
||||
The structure defines which modules to display and in what order. It consists of module names separated by colons (:).
|
||||
For example: {startBold}title:separator:os:kernel:uptime{endBold}
|
||||
|
||||
To list all available modules, use {startBold}--list-modules{endBold}
|
||||
|
||||
|
||||
.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.
|
||||
Fastfetch uses JSONC (JSON with Comments) for configuration files. These files must have the .jsonc extension.
|
||||
|
||||
A JSONC config file is a JSON file that also supports comments
|
||||
with (// and /* */). Those files must have the extension '.jsonc'.
|
||||
You can generate a default config file using {startBold}--gen-config{endBold}. By default, the config file is saved at {startBold}~/.config/fastfetch/config.jsonc{endBold}.
|
||||
|
||||
The specified configuration/preset files are searched in the following order:
|
||||
The configuration/preset files are searched in the following locations (in order):
|
||||
|
||||
{startBold}1.{endBold} relative to the current working directory
|
||||
{startBold}1.{endBold} Relative to the current working directory
|
||||
|
||||
{startBold}2.{endBold} relative to ~/.local/share/fastfetch/presets/
|
||||
{startBold}2.{endBold} Relative to ~/.local/share/fastfetch/presets/
|
||||
|
||||
{startBold}3.{endBold} relative to /usr/share/fastfetch/presets/
|
||||
{startBold}3.{endBold} Relative to /usr/share/fastfetch/presets/
|
||||
|
||||
Fastfetch provides some default presets. List them with --list-presets.
|
||||
For detailed information on logo options, module configuration, and formatting, visit:
|
||||
{startBold}https://github.com/fastfetch-cli/fastfetch/wiki/Configuration{endBold}
|
||||
|
||||
Fastfetch provides several built-in presets. List them with {startBold}--list-presets{endBold}.
|
||||
|
||||
.SS JSON Schema
|
||||
A JSON schema is available for editor intelligence when editing the configuration file. Add the following line at the beginning of your config file:
|
||||
|
||||
{startBold}"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json"{endBold}
|
||||
"""
|
||||
|
||||
# text displayed in the "EXAMPLE" section
|
||||
exampleSection = """
|
||||
.SS Config files:
|
||||
exampleSection = f"""
|
||||
.SS Basic Usage
|
||||
{startBold}fastfetch{endBold}
|
||||
|
||||
.SS Use a specific logo
|
||||
{startBold}fastfetch --logo arch{endBold}
|
||||
|
||||
.SS Custom structure
|
||||
{startBold}fastfetch --structure title:os:kernel:uptime:memory{endBold}
|
||||
|
||||
.SS Generate a config file
|
||||
{startBold}fastfetch --gen-config{endBold}
|
||||
|
||||
.SS Use a preset
|
||||
{startBold}fastfetch --config neofetch{endBold}
|
||||
|
||||
.SS Config File Example
|
||||
.nf
|
||||
// ~/.config/fastfetch/config.jsonc
|
||||
{
|
||||
{{
|
||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
||||
"logo": {{
|
||||
"type": "auto",
|
||||
"source": "arch"
|
||||
}},
|
||||
"display": {{
|
||||
"separator": ": ",
|
||||
"color": {{
|
||||
"keys": "blue",
|
||||
"title": "red"
|
||||
}},
|
||||
"key": {{
|
||||
"width": 12
|
||||
}}
|
||||
}},
|
||||
"modules": [
|
||||
"title",
|
||||
"separator",
|
||||
"module1",
|
||||
{
|
||||
"type": "module2",
|
||||
"module2-option": "value"
|
||||
}
|
||||
"os",
|
||||
"kernel",
|
||||
"uptime",
|
||||
{{
|
||||
"type": "memory",
|
||||
"format": "{{used}}/{{total}} ({{used_percent}}%)"
|
||||
}}
|
||||
]
|
||||
}
|
||||
}}
|
||||
.fi
|
||||
"""
|
||||
|
||||
# text displayed in the "BUGS" section
|
||||
bugSection = "Please report bugs to : \
|
||||
https://github.com/fastfetch-cli/fastfetch/issues"
|
||||
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"
|
||||
# text displayed in the "AUTHORS" section
|
||||
authorsSection = "Fastfetch is developed by a team of contributors on GitHub.\nVisit https://github.com/fastfetch-cli/fastfetch for more information."
|
||||
|
||||
|
||||
###### Argument decoration ######
|
||||
@@ -130,7 +171,7 @@ wikiSection = "Fastfetch github wiki : https://github.com/fastfetch-cli/fastfetc
|
||||
|
||||
# if an optional argument is displayed as [?optArg] (with "optArg" underlined)
|
||||
# this value should be f"[?{startUnderline}"
|
||||
startOptionalArgument = 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}]"
|
||||
@@ -161,7 +202,7 @@ def main():
|
||||
for line in versionFile:
|
||||
researchVersion = search(r"^\s*VERSION (\d+\.\d+\.\d+)$", line)
|
||||
if (researchVersion):
|
||||
print(f"\"{researchVersion.group(1)}\"", end=" ")
|
||||
print(f"\"Fastfetch {researchVersion.group(1)}\"", end=" ")
|
||||
break
|
||||
|
||||
print(f"\"{titlePage}\"")
|
||||
@@ -177,13 +218,13 @@ def main():
|
||||
|
||||
print(".SH SYNOPSIS")
|
||||
print(".B fastfetch")
|
||||
print(f"[{startUnderline}OPTIONS{endUnderline}]")\
|
||||
print(f"[{startUnderline}OPTIONS{endUnderline}...]")
|
||||
|
||||
|
||||
###### Wiki ######
|
||||
###### Description ######
|
||||
|
||||
print(".SH WIKI")
|
||||
print(wikiSection)
|
||||
print(".SH DESCRIPTION")
|
||||
print(descriptionSection)
|
||||
|
||||
|
||||
###### Configuration ######
|
||||
@@ -202,7 +243,7 @@ def main():
|
||||
for key, value in helpFileData.items():
|
||||
|
||||
# print new subsection
|
||||
print(f".SS {key}:")
|
||||
print(f".SS {key}")
|
||||
|
||||
# loop through every option in a section
|
||||
for option in value:
|
||||
@@ -237,7 +278,25 @@ def main():
|
||||
print(startMandatoryArgument + option['arg']['type'] + endMandatoryArgument, end="")
|
||||
|
||||
# description
|
||||
print(f"\n {option['desc']} \n")
|
||||
print()
|
||||
|
||||
# If desc is a list, join with newlines and proper spacing
|
||||
if isinstance(option['desc'], list):
|
||||
desc_text = "\n ".join(option['desc'])
|
||||
print(f" {desc_text}")
|
||||
else:
|
||||
print(f" {option['desc']}")
|
||||
|
||||
# Add remarks if available
|
||||
if "remark" in keyList:
|
||||
print()
|
||||
if isinstance(option['remark'], list):
|
||||
for remark in option['remark']:
|
||||
print(f" {remark}")
|
||||
else:
|
||||
print(f" {option['remark']}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
###### Examples ######
|
||||
@@ -246,12 +305,22 @@ def main():
|
||||
print(exampleSection)
|
||||
|
||||
|
||||
###### See Also ######
|
||||
|
||||
print(".SH \"SEE ALSO\"")
|
||||
print(".BR neofetch (1)")
|
||||
|
||||
|
||||
###### Bugs ######
|
||||
|
||||
print(".SH BUGS")
|
||||
print(bugSection)
|
||||
|
||||
|
||||
###### Authors ######
|
||||
|
||||
print(".SH AUTHORS")
|
||||
print(authorsSection)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from requests import get as http_get
|
||||
import sys
|
||||
|
||||
class PciDeviceModel:
|
||||
def __init__(self, id: int, name: str):
|
||||
@@ -13,14 +13,10 @@ class PciVendorModel:
|
||||
self.name = name
|
||||
self.devices = []
|
||||
|
||||
def main(keep_vendor_list: set):
|
||||
def main(keep_vendor_list: set, pci_ids_path: str):
|
||||
vendors = []
|
||||
try:
|
||||
with open('pci.ids', 'r') as f:
|
||||
full_text = f.read()
|
||||
except FileNotFoundError:
|
||||
response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids')
|
||||
full_text = response.text
|
||||
with open(pci_ids_path, 'r') as f:
|
||||
full_text = f.read()
|
||||
|
||||
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
|
||||
for line in dev_list_text.split('\n'):
|
||||
@@ -80,6 +76,8 @@ const FFPciVendor ffPciVendors[] = {{
|
||||
print(code)
|
||||
|
||||
if __name__ == '__main__':
|
||||
len(sys.argv) == 2 or sys.exit('Usage: gen-pciids.py </path/to/pci.ids>')
|
||||
|
||||
# From <src/detection/gpu/gpu.c>
|
||||
main({
|
||||
0x106b, # Apple
|
||||
@@ -94,4 +92,4 @@ if __name__ == '__main__':
|
||||
0x1ab8, # Parallel
|
||||
0x1414, # Microsoft
|
||||
0x108e, # Oracle
|
||||
})
|
||||
}, sys.argv[1])
|
||||
|
||||
Vendored
-383
@@ -1,383 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// \file
|
||||
/// \mainpage
|
||||
/// AGS Library Overview
|
||||
/// --------------------
|
||||
/// This document provides an overview of the AGS (AMD GPU Services) library. The AGS library provides software developers with the ability to query
|
||||
/// AMD GPU software and hardware state information that is not normally available through standard operating systems or graphic APIs.
|
||||
///
|
||||
/// The latest version of the API is publicly hosted here: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/.
|
||||
/// It is also worth checking http://gpuopen.com/gaming-product/amd-gpu-services-ags-library/ for any updates and articles on AGS.
|
||||
/// \internal
|
||||
/// Online documentation is publicly hosted here: http://gpuopen-librariesandsdks.github.io/ags/
|
||||
/// \endinternal
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 6.2 since version 6.1
|
||||
/// ---------------------------------------
|
||||
/// AGS 6.2 includes the following updates:
|
||||
/// * Shader clock intrinsics
|
||||
/// * Minor improvements and fixes
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 6.1 since version 6.0
|
||||
/// ---------------------------------------
|
||||
/// AGS 6.1 includes the following updates:
|
||||
/// * RDNA3 detection
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 6.0 since version 5.4.2
|
||||
/// ---------------------------------------
|
||||
/// AGS 6.0 includes the following updates:
|
||||
/// * DX12 ray tracing hit token for RDNA2 hardware.
|
||||
/// * Shader intrinsic that exposes ReadLaneAt in DX12.
|
||||
/// * Shader intrinsics that expose explicit float conversions in DX12.
|
||||
/// * Refactored and revised API to minimize user error.
|
||||
/// * Added agsGetVersionNumber.
|
||||
/// * Detection for external GPUs.
|
||||
/// * Detection of RDNA2 architecture.
|
||||
/// * Grouped the more established intrinsics together into per year support.
|
||||
/// * Function pointer typedefs for the API
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 5.4.2 since version 5.4.1
|
||||
/// ---------------------------------------
|
||||
/// AGS 5.4.2 includes the following updates:
|
||||
/// * sharedMemoryInBytes has been reinstated.
|
||||
/// * Clock speed returned for APUs.
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 5.4.1 since version 5.4.0
|
||||
/// ---------------------------------------
|
||||
/// AGS 5.4.1 includes the following updates:
|
||||
/// * AsicFamily_Count to help with code maintenance.
|
||||
/// * Visual Studio 2019 support.
|
||||
/// * x86 support
|
||||
/// * BaseInstance and BaseVertex intrinsics along with corresponding caps bits.
|
||||
/// * GetWaveSize intrinsic along with corresponding caps bits.
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 5.4 since version 5.3
|
||||
/// ---------------------------------------
|
||||
/// AGS 5.4 includes the following updates:
|
||||
/// * A more detailed description of the GPU architecture, now including RDNA GPUs.
|
||||
/// * Radeon 7 core and memory speeds returned.
|
||||
/// * Draw index and Atomic U64 intrinsics for both DX11 and DX12.
|
||||
///
|
||||
/// ---------------------------------------
|
||||
/// What's new in AGS 5.3 since version 5.2
|
||||
/// ---------------------------------------
|
||||
/// AGS 5.3 includes the following updates:
|
||||
/// * DX11 deferred context support for Multi Draw Indirect and UAV Overlap extensions.
|
||||
/// * A Radeon Software Version helper to determine whether the installed driver meets your game's minimum driver version requirements.
|
||||
/// * Freesync HDR Gamma 2.2 mode which uses a 1010102 swapchain and can be considered as an alternative to using the 64 bit swapchain required for Freesync HDR scRGB.
|
||||
///
|
||||
/// Using the AGS library
|
||||
/// ---------------------
|
||||
/// It is recommended to take a look at the source code for the samples that come with the AGS SDK:
|
||||
/// * AGSSample
|
||||
/// * CrossfireSample
|
||||
/// * EyefinitySample
|
||||
/// The AGSSample application is the simplest of the three examples and demonstrates the code required to initialize AGS and use it to query the GPU and Eyefinity state.
|
||||
/// The CrossfireSample application demonstrates the use of the new API to transfer resources on GPUs in Crossfire mode. Lastly, the EyefinitySample application provides a more
|
||||
/// extensive example of Eyefinity setup than the basic example provided in AGSSample.
|
||||
/// There are other samples on Github that demonstrate the DirectX shader extensions, such as the Barycentrics11 and Barycentrics12 samples.
|
||||
///
|
||||
/// To add AGS support to an existing project, follow these steps:
|
||||
/// * Link your project against the correct import library. Choose from either the 32 bit or 64 bit version.
|
||||
/// * Copy the AGS dll into the same directory as your game executable.
|
||||
/// * Include the amd_ags.h header file from your source code.
|
||||
/// * Include the AGS hlsl files if you are using the shader intrinsics.
|
||||
/// * Declare a pointer to an AGSContext and make this available for all subsequent calls to AGS.
|
||||
/// * On game initialization, call \ref agsInitialize passing in the address of the context. On success, this function will return a valid context pointer.
|
||||
///
|
||||
/// Don't forget to cleanup AGS by calling \ref agsDeInitialize when the app exits, after the device has been destroyed.
|
||||
|
||||
#ifndef AMD_AGS_H
|
||||
#define AMD_AGS_H
|
||||
|
||||
#define AMD_AGS_VERSION_MAJOR 6 ///< AGS major version
|
||||
#define AMD_AGS_VERSION_MINOR 2 ///< AGS minor version
|
||||
#define AMD_AGS_VERSION_PATCH 0 ///< AGS patch version
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// \defgroup Defines AGS defines
|
||||
/// @{
|
||||
#if defined (AGS_GCC)
|
||||
#define AMD_AGS_API
|
||||
#else
|
||||
#define AMD_AGS_API __declspec(dllexport) ///< AGS exported functions
|
||||
#endif
|
||||
|
||||
#define AGS_MAKE_VERSION( major, minor, patch ) ( ( major << 22 ) | ( minor << 12 ) | patch ) ///< Macro to create the app and engine versions for the fields in \ref AGSDX12ExtensionParams and \ref AGSDX11ExtensionParams and the Radeon Software Version
|
||||
#define AGS_UNSPECIFIED_VERSION 0xFFFFAD00 ///< Use this to specify no version
|
||||
#define AGS_CURRENT_VERSION AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ) ///< Macro to return the current AGS version as defined by the AGS header file
|
||||
/// @}
|
||||
|
||||
/// \defgroup enums General enumerations
|
||||
/// @{
|
||||
|
||||
/// The return codes
|
||||
typedef enum AGSReturnCode
|
||||
{
|
||||
AGS_SUCCESS, ///< Successful function call
|
||||
AGS_FAILURE, ///< Failed to complete call for some unspecified reason
|
||||
AGS_INVALID_ARGS, ///< Invalid arguments into the function
|
||||
AGS_OUT_OF_MEMORY, ///< Out of memory when allocating space internally
|
||||
AGS_MISSING_D3D_DLL, ///< Returned when a D3D dll fails to load
|
||||
AGS_LEGACY_DRIVER, ///< Returned if a feature is not present in the installed driver
|
||||
AGS_NO_AMD_DRIVER_INSTALLED, ///< Returned if the AMD GPU driver does not appear to be installed
|
||||
AGS_EXTENSION_NOT_SUPPORTED, ///< Returned if the driver does not support the requested driver extension
|
||||
AGS_ADL_FAILURE, ///< Failure in ADL (the AMD Display Library)
|
||||
AGS_DX_FAILURE, ///< Failure from DirectX runtime
|
||||
AGS_D3DDEVICE_NOT_CREATED ///< Failure due to not creating the D3D device successfully via AGS.
|
||||
} AGSReturnCode;
|
||||
|
||||
/// @}
|
||||
|
||||
typedef struct AGSContext AGSContext; ///< All function calls in AGS require a pointer to a context. This is generated via \ref agsInitialize
|
||||
|
||||
/// The rectangle struct used by AGS.
|
||||
typedef struct AGSRect
|
||||
{
|
||||
int offsetX; ///< Offset on X axis
|
||||
int offsetY; ///< Offset on Y axis
|
||||
int width; ///< Width of rectangle
|
||||
int height; ///< Height of rectangle
|
||||
} AGSRect;
|
||||
|
||||
/// The display info struct used to describe a display enumerated by AGS
|
||||
typedef struct AGSDisplayInfo
|
||||
{
|
||||
char name[ 256 ]; ///< The name of the display
|
||||
char displayDeviceName[ 32 ]; ///< The display device name, i.e. DISPLAY_DEVICE::DeviceName
|
||||
|
||||
unsigned int isPrimaryDisplay : 1; ///< Whether this display is marked as the primary display
|
||||
unsigned int HDR10 : 1; ///< HDR10 is supported on this display
|
||||
unsigned int dolbyVision : 1; ///< Dolby Vision is supported on this display
|
||||
unsigned int freesync : 1; ///< Freesync is supported on this display
|
||||
unsigned int freesyncHDR : 1; ///< Freesync HDR is supported on this display
|
||||
unsigned int eyefinityInGroup : 1; ///< The display is part of the Eyefinity group
|
||||
unsigned int eyefinityPreferredDisplay : 1; ///< The display is the preferred display in the Eyefinity group for displaying the UI
|
||||
unsigned int eyefinityInPortraitMode : 1; ///< The display is in the Eyefinity group but in portrait mode
|
||||
unsigned int reservedPadding : 24; ///< Reserved for future use
|
||||
|
||||
int maxResolutionX; ///< The maximum supported resolution of the unrotated display
|
||||
int maxResolutionY; ///< The maximum supported resolution of the unrotated display
|
||||
float maxRefreshRate; ///< The maximum supported refresh rate of the display
|
||||
|
||||
AGSRect currentResolution; ///< The current resolution and position in the desktop, ignoring Eyefinity bezel compensation
|
||||
AGSRect visibleResolution; ///< The visible resolution and position. When Eyefinity bezel compensation is enabled this will
|
||||
///< be the sub region in the Eyefinity single large surface (SLS)
|
||||
float currentRefreshRate; ///< The current refresh rate
|
||||
|
||||
int eyefinityGridCoordX; ///< The X coordinate in the Eyefinity grid. -1 if not in an Eyefinity group
|
||||
int eyefinityGridCoordY; ///< The Y coordinate in the Eyefinity grid. -1 if not in an Eyefinity group
|
||||
|
||||
double chromaticityRedX; ///< Red display primary X coord
|
||||
double chromaticityRedY; ///< Red display primary Y coord
|
||||
|
||||
double chromaticityGreenX; ///< Green display primary X coord
|
||||
double chromaticityGreenY; ///< Green display primary Y coord
|
||||
|
||||
double chromaticityBlueX; ///< Blue display primary X coord
|
||||
double chromaticityBlueY; ///< Blue display primary Y coord
|
||||
|
||||
double chromaticityWhitePointX; ///< White point X coord
|
||||
double chromaticityWhitePointY; ///< White point Y coord
|
||||
|
||||
double screenDiffuseReflectance; ///< Percentage expressed between 0 - 1
|
||||
double screenSpecularReflectance; ///< Percentage expressed between 0 - 1
|
||||
|
||||
double minLuminance; ///< The minimum luminance of the display in nits
|
||||
double maxLuminance; ///< The maximum luminance of the display in nits
|
||||
double avgLuminance; ///< The average luminance of the display in nits
|
||||
|
||||
int logicalDisplayIndex; ///< The internally used index of this display
|
||||
int adlAdapterIndex; ///< The internally used ADL adapter index
|
||||
int reserved; ///< reserved field
|
||||
} AGSDisplayInfo;
|
||||
|
||||
/// The ASIC family
|
||||
typedef enum AsicFamily
|
||||
{
|
||||
AsicFamily_Unknown, ///< Unknown architecture, potentially from another IHV. Check \ref AGSDeviceInfo::vendorId
|
||||
AsicFamily_PreGCN, ///< Pre GCN architecture.
|
||||
AsicFamily_GCN1, ///< AMD GCN 1 architecture: Oland, Cape Verde, Pitcairn & Tahiti.
|
||||
AsicFamily_GCN2, ///< AMD GCN 2 architecture: Hawaii & Bonaire. This also includes APUs Kaveri and Carrizo.
|
||||
AsicFamily_GCN3, ///< AMD GCN 3 architecture: Tonga & Fiji.
|
||||
AsicFamily_GCN4, ///< AMD GCN 4 architecture: Polaris.
|
||||
AsicFamily_Vega, ///< AMD Vega architecture, including Raven Ridge (ie AMD Ryzen CPU + AMD Vega GPU).
|
||||
AsicFamily_RDNA, ///< AMD RDNA architecture
|
||||
AsicFamily_RDNA2, ///< AMD RDNA2 architecture
|
||||
AsicFamily_RDNA3, ///< AMD RDNA3 architecture
|
||||
|
||||
AsicFamily_Count ///< Number of enumerated ASIC families
|
||||
} AsicFamily;
|
||||
|
||||
/// The device info struct used to describe a physical GPU enumerated by AGS
|
||||
typedef struct AGSDeviceInfo
|
||||
{
|
||||
const char* adapterString; ///< The adapter name string
|
||||
AsicFamily asicFamily; ///< Set to Unknown if not AMD hardware
|
||||
unsigned int isAPU : 1; ///< Whether this device is an APU
|
||||
unsigned int isPrimaryDevice : 1; ///< Whether this device is marked as the primary device
|
||||
unsigned int isExternal :1; ///< Whether this device is a detachable, external device
|
||||
unsigned int reservedPadding : 29; ///< Reserved for future use
|
||||
|
||||
int vendorId; ///< The vendor id
|
||||
int deviceId; ///< The device id
|
||||
int revisionId; ///< The revision id
|
||||
|
||||
int numCUs; ///< Number of compute units
|
||||
int numWGPs; ///< Number of RDNA Work Group Processors. Only valid if ASIC is RDNA onwards.
|
||||
|
||||
int numROPs; ///< Number of ROPs
|
||||
int coreClock; ///< Core clock speed at 100% power in MHz
|
||||
int memoryClock; ///< Memory clock speed at 100% power in MHz
|
||||
int memoryBandwidth; ///< Memory bandwidth in MB/s
|
||||
float teraFlops; ///< Teraflops of GPU. Zero if not GCN onwards. Calculated from iCoreClock * iNumCUs * 64 Pixels/clk * 2 instructions/MAD
|
||||
|
||||
unsigned long long localMemoryInBytes; ///< The size of local memory in bytes. 0 for non AMD hardware.
|
||||
unsigned long long sharedMemoryInBytes; ///< The size of system memory available to the GPU in bytes. It is important to factor this into your VRAM budget for APUs
|
||||
///< as the reported local memory will only be a small fraction of the total memory available to the GPU.
|
||||
|
||||
int numDisplays; ///< The number of active displays found to be attached to this adapter.
|
||||
AGSDisplayInfo* displays; ///< List of displays allocated by AGS to be numDisplays in length.
|
||||
|
||||
int eyefinityEnabled; ///< Indicates if Eyefinity is active
|
||||
int eyefinityGridWidth; ///< Contains width of the multi-monitor grid that makes up the Eyefinity Single Large Surface.
|
||||
int eyefinityGridHeight; ///< Contains height of the multi-monitor grid that makes up the Eyefinity Single Large Surface.
|
||||
int eyefinityResolutionX; ///< Contains width in pixels of the multi-monitor Single Large Surface.
|
||||
int eyefinityResolutionY; ///< Contains height in pixels of the multi-monitor Single Large Surface.
|
||||
int eyefinityBezelCompensated; ///< Indicates if bezel compensation is used for the current SLS display area. 1 if enabled, and 0 if disabled.
|
||||
|
||||
int adlAdapterIndex; ///< Internally used index into the ADL list of adapters
|
||||
int reserved; ///< reserved field
|
||||
} AGSDeviceInfo;
|
||||
|
||||
/// \defgroup general General API functions
|
||||
/// API for initialization, cleanup, HDR display modes and Crossfire GPU count
|
||||
/// @{
|
||||
|
||||
typedef void* (__stdcall *AGS_ALLOC_CALLBACK)( size_t allocationSize ); ///< AGS user defined allocation prototype
|
||||
typedef void (__stdcall *AGS_FREE_CALLBACK)( void* allocationPtr ); ///< AGS user defined free prototype
|
||||
|
||||
/// The configuration options that can be passed in to \ref agsInitialize
|
||||
typedef struct AGSConfiguration
|
||||
{
|
||||
AGS_ALLOC_CALLBACK allocCallback; ///< Optional memory allocation callback. If not supplied, malloc() is used
|
||||
AGS_FREE_CALLBACK freeCallback; ///< Optional memory freeing callback. If not supplied, free() is used
|
||||
} AGSConfiguration;
|
||||
|
||||
/// The top level GPU information returned from \ref agsInitialize
|
||||
typedef struct AGSGPUInfo
|
||||
{
|
||||
const char* driverVersion; ///< The AMD driver package version
|
||||
const char* radeonSoftwareVersion; ///< The Radeon Software Version
|
||||
|
||||
int numDevices; ///< Number of GPUs in the system
|
||||
AGSDeviceInfo* devices; ///< List of GPUs in the system
|
||||
} AGSGPUInfo;
|
||||
|
||||
/// The struct to specify the display settings to the driver.
|
||||
typedef struct AGSDisplaySettings AGSDisplaySettings;
|
||||
|
||||
|
||||
/// The result returned from \ref agsCheckDriverVersion
|
||||
typedef enum AGSDriverVersionResult
|
||||
{
|
||||
AGS_SOFTWAREVERSIONCHECK_OK, ///< The reported Radeon Software Version is newer or the same as the required version
|
||||
AGS_SOFTWAREVERSIONCHECK_OLDER, ///< The reported Radeon Software Version is older than the required version
|
||||
AGS_SOFTWAREVERSIONCHECK_UNDEFINED ///< The check could not determine as result. This could be because it is a private or custom driver or just invalid arguments.
|
||||
} AGSDriverVersionResult;
|
||||
|
||||
///
|
||||
/// Helper function to check the installed software version against the required software version.
|
||||
///
|
||||
/// \param [in] radeonSoftwareVersionReported The Radeon Software Version returned from \ref AGSGPUInfo::radeonSoftwareVersion.
|
||||
/// \param [in] radeonSoftwareVersionRequired The Radeon Software Version to check against. This is specificed using \ref AGS_MAKE_VERSION.
|
||||
/// \return The result of the check.
|
||||
///
|
||||
AMD_AGS_API AGSDriverVersionResult agsCheckDriverVersion( const char* radeonSoftwareVersionReported, unsigned int radeonSoftwareVersionRequired );
|
||||
|
||||
///
|
||||
/// Function to return the AGS version number.
|
||||
///
|
||||
/// \return The version number made using AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ).
|
||||
///
|
||||
AMD_AGS_API int agsGetVersionNumber();
|
||||
|
||||
///
|
||||
/// Function used to initialize the AGS library.
|
||||
/// agsVersion must be specified as AGS_CURRENT_VERSION or the call will return \ref AGS_INVALID_ARGS.
|
||||
/// Must be called prior to any of the subsequent AGS API calls.
|
||||
/// Must be called prior to ID3D11Device or ID3D12Device creation.
|
||||
/// \note The caller of this function should handle the possibility of the call failing in the cases below. One option is to do a vendor id check and only call \ref agsInitialize if there is an AMD GPU present.
|
||||
/// \note This function will fail with \ref AGS_NO_AMD_DRIVER_INSTALLED if there is no AMD driver found on the system.
|
||||
/// \note This function will fail with \ref AGS_LEGACY_DRIVER in Catalyst versions before 12.20.
|
||||
///
|
||||
/// \param [in] agsVersion The API version specified using the \ref AGS_CURRENT_VERSION macro. If this does not match the version in the binary this initialization call will fail.
|
||||
/// \param [in] config Optional pointer to a AGSConfiguration struct to override the default library configuration.
|
||||
/// \param [out] context Address of a pointer to a context. This function allocates a context on the heap which is then required for all subsequent API calls.
|
||||
/// \param [out] gpuInfo Optional pointer to a AGSGPUInfo struct which will get filled in for all the GPUs in the system.
|
||||
///
|
||||
AMD_AGS_API AGSReturnCode agsInitialize( int agsVersion, const AGSConfiguration* config, AGSContext** context, AGSGPUInfo* gpuInfo );
|
||||
|
||||
///
|
||||
/// Function used to clean up the AGS library.
|
||||
///
|
||||
/// \param [in] context Pointer to a context. This function will deallocate the context from the heap.
|
||||
///
|
||||
AMD_AGS_API AGSReturnCode agsDeInitialize( AGSContext* context );
|
||||
|
||||
///
|
||||
/// Function used to set a specific display into HDR mode
|
||||
/// \note Setting all of the values apart from color space and transfer function to zero will cause the display to use defaults.
|
||||
/// \note Call this function after each mode change (switch to fullscreen, any change in swapchain etc).
|
||||
/// \note HDR10 PQ mode requires a 1010102 swapchain.
|
||||
/// \note HDR10 scRGB mode requires an FP16 swapchain.
|
||||
/// \note Freesync HDR scRGB mode requires an FP16 swapchain.
|
||||
/// \note Freesync HDR Gamma 2.2 mode requires a 1010102 swapchain.
|
||||
/// \note Dolby Vision requires a 8888 UNORM swapchain.
|
||||
///
|
||||
/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize
|
||||
/// \param [in] deviceIndex The index of the device listed in \ref AGSGPUInfo::devices.
|
||||
/// \param [in] displayIndex The index of the display listed in \ref AGSDeviceInfo::displays.
|
||||
/// \param [in] settings Pointer to the display settings to use.
|
||||
///
|
||||
AMD_AGS_API AGSReturnCode agsSetDisplayMode( AGSContext* context, int deviceIndex, int displayIndex, const AGSDisplaySettings* settings );
|
||||
|
||||
/// @}
|
||||
|
||||
/// @}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AMD_AGS_H
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK",
|
||||
"license": "MIT (embeded in source)",
|
||||
"version": "AGS v6.2.0",
|
||||
"author": "Advanced Micro Devices, Inc",
|
||||
"modified": "CarterLi"
|
||||
}
|
||||
+2596
File diff suppressed because it is too large
Load Diff
+46
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright (c) 2016 - 2022 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// MIT LICENSE:
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/// \file adl_sdk.h
|
||||
/// \brief Contains the definition of the Memory Allocation Callback.\n <b>Included in ADL SDK</b>
|
||||
///
|
||||
/// \n\n
|
||||
/// This file contains the definition of the Memory Allocation Callback.\n
|
||||
/// It also includes definitions of the respective structures and constants.\n
|
||||
/// <b> This is the only header file to be included in a C/C++ project using ADL </b>
|
||||
|
||||
#ifndef ADL_SDK_H_
|
||||
#define ADL_SDK_H_
|
||||
|
||||
#include "adl_structures.h"
|
||||
|
||||
#if defined (LINUX)
|
||||
#define __stdcall
|
||||
#endif /* (LINUX) */
|
||||
|
||||
/// Memory Allocation Call back
|
||||
typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int );
|
||||
|
||||
#define ADL_SDK_MAJOR_VERSION 17
|
||||
#define ADL_SDK_MINOR_VERSION 1
|
||||
|
||||
#endif /* ADL_SDK_H_ */
|
||||
+4289
File diff suppressed because it is too large
Load Diff
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/display-library",
|
||||
"license": "MIT (embeded in source)",
|
||||
"version": "ADL SDK 17.1",
|
||||
"author": "Advanced Micro Devices, Inc"
|
||||
}
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"home": "https://github.com/ibireme/yyjson",
|
||||
"license": "MIT ( embed in source )",
|
||||
"version": "0.10.0",
|
||||
"version": "0.11.1",
|
||||
"author": "ibireme"
|
||||
}
|
||||
|
||||
Vendored
+2508
-1264
File diff suppressed because it is too large
Load Diff
Vendored
+800
-570
File diff suppressed because it is too large
Load Diff
@@ -134,7 +134,7 @@ void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
|
||||
int len = snprintf(str, sizeof str, "%.3fms", ms);
|
||||
if (thres > 0)
|
||||
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
|
||||
printf("\e[s\e[1A\e[9999999C\e[%dD%s\e[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
printf("\e7\e[1A\e[9999999C\e[%dD%s\e8", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-13
@@ -32,10 +32,16 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
|
||||
ffStrbufAppend(buffer, (FFstrbuf*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_FLOAT:
|
||||
ffStrbufAppendF(buffer, "%f", *(float*)formatarg->value);
|
||||
if (instance.config.display.fractionNdigits >= 0)
|
||||
ffStrbufAppendF(buffer, "%.*f", instance.config.display.fractionNdigits, *(float*)formatarg->value);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "%g", *(float*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_DOUBLE:
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
if (instance.config.display.fractionNdigits >= 0)
|
||||
ffStrbufAppendF(buffer, "%.*f", instance.config.display.fractionNdigits, *(double*)formatarg->value);
|
||||
else
|
||||
ffStrbufAppendF(buffer, "%g", *(double*)formatarg->value);
|
||||
break;
|
||||
case FF_FORMAT_ARG_TYPE_BOOL:
|
||||
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
|
||||
@@ -108,6 +114,7 @@ static inline bool formatArgSet(const FFformatarg* arg)
|
||||
{
|
||||
return arg->value != NULL && (
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_DOUBLE && *(double*)arg->value > 0.0) || //Also is false for NaN
|
||||
(arg->type == FF_FORMAT_ARG_TYPE_FLOAT && *(float*)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((char*)arg->value)) ||
|
||||
@@ -259,24 +266,33 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n
|
||||
continue;
|
||||
}
|
||||
|
||||
//test for constant, if so evaluate it
|
||||
//test for constant or env var, if so evaluate it
|
||||
if (firstChar == '$')
|
||||
{
|
||||
char* pend = NULL;
|
||||
int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10);
|
||||
uint32_t index = (uint32_t) indexSigned;
|
||||
bool backward = indexSigned < 0;
|
||||
|
||||
if (indexSigned == 0 || *pend != '\0' || instance.config.display.constants.length < index)
|
||||
if (pend == placeholderValue.chars + 1)
|
||||
{
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
continue;
|
||||
// treat placeholder as an environment variable
|
||||
char* envValue = getenv(placeholderValue.chars + 1);
|
||||
if (envValue)
|
||||
ffStrbufAppendS(buffer, envValue);
|
||||
else
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// treat placeholder as a constant
|
||||
uint32_t index = (uint32_t) (indexSigned < 0 ? (int32_t) instance.config.display.constants.length + indexSigned : indexSigned - 1);
|
||||
|
||||
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, backward
|
||||
? instance.config.display.constants.length - index
|
||||
: index - 1);
|
||||
ffStrbufAppend(buffer, item);
|
||||
if (*pend != '\0' || instance.config.display.constants.length <= index)
|
||||
appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length);
|
||||
else
|
||||
{
|
||||
FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, index);
|
||||
ffStrbufAppend(buffer, item);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -1,4 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/init.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/thread.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
@@ -104,6 +105,7 @@ void ffStart(void)
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
if (instance.config.display.noBuffer)
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
else
|
||||
@@ -227,15 +229,15 @@ void ffListFeatures(void)
|
||||
#if FF_HAVE_GLX
|
||||
"glx\n"
|
||||
#endif
|
||||
#if FF_HAVE_OSMESA
|
||||
"osmesa\n"
|
||||
#endif
|
||||
#if FF_HAVE_OPENCL
|
||||
"opencl\n"
|
||||
#endif
|
||||
#if FF_HAVE_FREETYPE
|
||||
"freetype\n"
|
||||
#endif
|
||||
#if FF_HAVE_PCIACCESS
|
||||
"libpciaccess\n"
|
||||
#endif
|
||||
#if FF_HAVE_PULSE
|
||||
"libpulse\n"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
void ffInitInstance(void);
|
||||
void ffStart(void);
|
||||
void ffFinish(void);
|
||||
void ffDestroyInstance(void);
|
||||
void ffListFeatures(void);
|
||||
+3
-21
@@ -19,8 +19,7 @@
|
||||
#define FF_INVALID_FD (-1)
|
||||
// procfs's file can be changed between read calls such as /proc/meminfo and /proc/uptime.
|
||||
// one safe way to read correct data is reading the whole file in a single read syscall
|
||||
// 8192 comes from procps-ng: https://gitlab.com/procps-ng/procps/-/blob/master/library/meminfo.c?ref_type=heads#L39
|
||||
#define PROC_FILE_BUFFSIZ 8192
|
||||
#define PROC_FILE_BUFFSIZ (32 * 1024)
|
||||
#endif
|
||||
|
||||
static inline FFNativeFD FFUnixFD2NativeFD(int unixfd)
|
||||
@@ -119,7 +118,6 @@ static inline bool ffPathExists(const char* path, FFPathType pathType)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if __APPLE__ // #1395
|
||||
struct stat fileStat;
|
||||
if(stat(path, &fileStat) != 0)
|
||||
return false;
|
||||
@@ -131,24 +129,6 @@ 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
|
||||
@@ -242,6 +222,8 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char*
|
||||
return false;
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void);
|
||||
|
||||
#ifdef _WIN32
|
||||
// Only O_RDONLY is supported
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
|
||||
|
||||
+16
-2
@@ -256,6 +256,11 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
|
||||
bool ffSuppressIO(bool suppress)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (instance.config.display.debugMode)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
static bool init = false;
|
||||
static int origOut = -1;
|
||||
static int origErr = -1;
|
||||
@@ -285,7 +290,7 @@ bool ffSuppressIO(bool suppress)
|
||||
|
||||
void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indentation, const char* folderName, bool pretty)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (dfd < 0)
|
||||
return;
|
||||
|
||||
@@ -310,7 +315,7 @@ void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indenta
|
||||
continue;
|
||||
|
||||
bool isDir = false;
|
||||
#ifndef __sun
|
||||
#if !defined(__sun) && !defined(__HAIKU__)
|
||||
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
|
||||
isDir = entry->d_type == DT_DIR;
|
||||
else
|
||||
@@ -353,3 +358,12 @@ void ffListFilesRecursively(const char* path, bool pretty)
|
||||
ffStrbufEnsureEndsWithC(&folder, '/');
|
||||
listFilesRecursively(folder.length, &folder, 0, NULL, pretty);
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void)
|
||||
{
|
||||
static FFNativeFD hNullFile = -1;
|
||||
if (hNullFile != -1)
|
||||
return hNullFile;
|
||||
hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
@@ -147,6 +147,14 @@ ssize_t ffReadFileDataRelative(HANDLE dfd, const char* fileName, size_t dataSize
|
||||
|
||||
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
|
||||
{
|
||||
if (in[0] == '~') {
|
||||
if ((in[1] == '/' || in[1] == '\\' || in[1] == '\0') && !ffStrContainsC(in, '%')) {
|
||||
ffStrbufSet(out, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(out, in + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD length = ExpandEnvironmentStringsA(in, NULL, 0);
|
||||
if (length <= 1) return false;
|
||||
|
||||
@@ -159,10 +167,15 @@ bool ffPathExpandEnv(const char* in, FFstrbuf* out)
|
||||
|
||||
bool ffSuppressIO(bool suppress)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (instance.config.display.debugMode)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
static bool init = false;
|
||||
static HANDLE hOrigOut = INVALID_HANDLE_VALUE;
|
||||
static HANDLE hOrigErr = INVALID_HANDLE_VALUE;
|
||||
static HANDLE hNullFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hNullFile = ffGetNullFD();
|
||||
static int fOrigOut = -1;
|
||||
static int fOrigErr = -1;
|
||||
static int fNullFile = -1;
|
||||
@@ -174,7 +187,6 @@ bool ffSuppressIO(bool suppress)
|
||||
|
||||
hOrigOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
hOrigErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
hNullFile = CreateFileW(L"NUL", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, NULL);
|
||||
fOrigOut = _dup(STDOUT_FILENO);
|
||||
fOrigErr = _dup(STDERR_FILENO);
|
||||
fNullFile = _open_osfhandle((intptr_t) hNullFile, 0);
|
||||
@@ -339,3 +351,23 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char*
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FFNativeFD ffGetNullFD(void)
|
||||
{
|
||||
static FFNativeFD hNullFile = INVALID_HANDLE_VALUE;
|
||||
if (hNullFile != INVALID_HANDLE_VALUE)
|
||||
return hNullFile;
|
||||
hNullFile = CreateFileW(
|
||||
L"NUL",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
&(SECURITY_ATTRIBUTES){
|
||||
.nLength = sizeof(SECURITY_ATTRIBUTES),
|
||||
.lpSecurityDescriptor = NULL,
|
||||
.bInheritHandle = TRUE,
|
||||
});
|
||||
return hNullFile;
|
||||
}
|
||||
|
||||
+44
-1
@@ -4,6 +4,7 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/time.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "modules/modules.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
@@ -170,6 +171,25 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module)
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchesJsonArray(const char* str, yyjson_val* val)
|
||||
{
|
||||
assert(val);
|
||||
|
||||
if (unsafe_yyjson_is_str(val))
|
||||
return ffStrEqualsIgnCase(str, unsafe_yyjson_get_str(val));
|
||||
|
||||
if (!unsafe_yyjson_is_arr(val)) return false;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_val* item;
|
||||
yyjson_arr_foreach(val, idx, max, item)
|
||||
{
|
||||
if (yyjson_is_str(item) && ffStrEqualsIgnCase(str, unsafe_yyjson_get_str(item)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
{
|
||||
yyjson_val* const root = yyjson_doc_get_root(instance.state.configDoc);
|
||||
@@ -197,6 +217,29 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
module = NULL;
|
||||
else if (yyjson_is_obj(module))
|
||||
{
|
||||
yyjson_val* conditions = yyjson_obj_get(module, "condition");
|
||||
if (conditions)
|
||||
{
|
||||
if (!yyjson_is_obj(conditions))
|
||||
return "Property 'conditions' must be an object";
|
||||
|
||||
yyjson_val* system = yyjson_obj_get(conditions, "system");
|
||||
if (system && !matchesJsonArray(ffVersionResult.sysName, system))
|
||||
continue;
|
||||
|
||||
system = yyjson_obj_get(conditions, "!system");
|
||||
if (system && matchesJsonArray(ffVersionResult.sysName, system))
|
||||
continue;
|
||||
|
||||
yyjson_val* arch = yyjson_obj_get(conditions, "arch");
|
||||
if (arch && !matchesJsonArray(ffVersionResult.architecture, arch))
|
||||
continue;
|
||||
|
||||
arch = yyjson_obj_get(conditions, "!arch");
|
||||
if (arch && matchesJsonArray(ffVersionResult.architecture, arch))
|
||||
continue;
|
||||
}
|
||||
|
||||
type = yyjson_get_str(yyjson_obj_get(module, "type"));
|
||||
if (!type) return "module object must contain a \"type\" key ( case sensitive )";
|
||||
if (yyjson_obj_size(module) == 1) // contains only Property type
|
||||
@@ -224,7 +267,7 @@ static const char* printJsonConfig(bool prepare, yyjson_mut_doc* jsonDoc)
|
||||
int len = snprintf(str, sizeof str, "%.3fms", ms);
|
||||
if (thres > 0)
|
||||
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
|
||||
printf("\e[s\e[1A\e[9999999C\e[%dD%s\e[u", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
printf("\e7\e[1A\e[9999999C\e[%dD%s\e8", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ void* ffLibraryLoad(const char* path, int maxVersion, ...);
|
||||
FF_MAYBE_UNUSED void* libraryObjectName = NULL; // Placeholder
|
||||
|
||||
#define FF_LIBRARY_LOAD_SYMBOL_ADDRESS(library, symbolMapping, symbolName, returnValue) \
|
||||
symbolMapping = (__typeof__(&symbolName)) &symbolName
|
||||
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);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#ifndef _WIN32
|
||||
#include <net/if.h>
|
||||
#else
|
||||
#define IF_NAMESIZE 16
|
||||
#define IF_NAMESIZE 0
|
||||
#endif
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "netif.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
@@ -8,13 +9,17 @@
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n))
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__NetBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t))
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
#elif defined(__OpenBSD__)
|
||||
# define ROUNDUP(a) ROUNDUP2((a), sizeof(int))
|
||||
@@ -47,6 +52,39 @@ get_rt_address(struct rt_msghdr *rtm, int desired)
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
#if defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
int mib[6] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY};
|
||||
size_t needed;
|
||||
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE char* buf = malloc(needed);
|
||||
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
||||
return false;
|
||||
|
||||
char* lim = buf + needed;
|
||||
struct rt_msghdr* rtm;
|
||||
for (char* next = buf; next < lim; next += rtm->rtm_msglen)
|
||||
{
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
struct sockaddr* sa = (struct sockaddr *)(rtm + 1);
|
||||
|
||||
if ((rtm->rtm_flags & RTF_GATEWAY) && (sa->sa_family == AF_INET))
|
||||
{
|
||||
struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(rtm, RTA_IFP);
|
||||
if (sdl->sdl_family == AF_LINK)
|
||||
{
|
||||
assert(sdl->sdl_nlen <= IF_NAMESIZE);
|
||||
memcpy(iface, sdl->sdl_data, sdl->sdl_nlen);
|
||||
iface[sdl->sdl_nlen] = '\0';
|
||||
*ifIndex = sdl->sdl_index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
//https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104
|
||||
|
||||
FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET);
|
||||
@@ -106,5 +144,7 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "netif.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// loosely based on Haiku's src/bin/network/route/route.cpp
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
// TODO: AF_INET6
|
||||
FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET);
|
||||
if (pfRoute < 0)
|
||||
return false;
|
||||
|
||||
struct ifconf config;
|
||||
config.ifc_len = sizeof(config.ifc_value);
|
||||
if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
|
||||
return false;
|
||||
|
||||
int size = config.ifc_value;
|
||||
if (size <= 0)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE void *buffer = malloc((size_t) size);
|
||||
if (buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
config.ifc_len = size;
|
||||
config.ifc_buf = buffer;
|
||||
if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0)
|
||||
return false;
|
||||
|
||||
struct ifreq *interface = (struct ifreq*)buffer;
|
||||
struct ifreq *end = (struct ifreq*)((uint8_t*)buffer + size);
|
||||
|
||||
while (interface < end) {
|
||||
if (interface->ifr_route.flags & RTF_DEFAULT) {
|
||||
strlcpy(iface, interface->ifr_name, IF_NAMESIZE);
|
||||
*ifIndex = if_nametoindex(interface->ifr_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t addressSize = 0;
|
||||
if (interface->ifr_route.destination != NULL)
|
||||
addressSize += interface->ifr_route.destination->sa_len;
|
||||
if (interface->ifr_route.mask != NULL)
|
||||
addressSize += interface->ifr_route.mask->sa_len;
|
||||
if (interface->ifr_route.gateway != NULL)
|
||||
addressSize += interface->ifr_route.gateway->sa_len;
|
||||
|
||||
interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE
|
||||
+ sizeof(struct route_entry) + addressSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#define FF_STR_INDIR(x) #x
|
||||
#define FF_STR(x) FF_STR_INDIR(x)
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
static bool getDefaultRouteIPv4(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r");
|
||||
if (!netRoute) return false;
|
||||
@@ -15,12 +15,38 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
// skip first line
|
||||
FF_UNUSED(fscanf(netRoute, "%*[^\n]\n"));
|
||||
|
||||
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu,
|
||||
unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, ...
|
||||
while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2)
|
||||
{
|
||||
if (destination != 0) continue;
|
||||
*ifIndex = if_nametoindex(iface);
|
||||
return true;
|
||||
}
|
||||
iface[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getDefaultRouteIPv6(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/ipv6_route", "r");
|
||||
if (!netRoute) return false;
|
||||
|
||||
uint32_t prefixLen;
|
||||
//destination, dest_prefix_len, source, src_prefix_len, next hop, metric, ref counter, use counter, flags, iface
|
||||
while (fscanf(netRoute, "%*s %x %*s %*s %*s %*s %*s %*s %*s %" FF_STR(IF_NAMESIZE) "s", &prefixLen, iface) == 2)
|
||||
{
|
||||
if (prefixLen != 0) continue;
|
||||
*ifIndex = if_nametoindex(iface);
|
||||
return true;
|
||||
}
|
||||
iface[0] = '\0';
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
if (getDefaultRouteIPv4(iface, ifIndex))
|
||||
return true;
|
||||
|
||||
return getDefaultRouteIPv6(iface, ifIndex);
|
||||
}
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
#include "netif.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <ws2tcpip.h> // AF_INET6, IN6_IS_ADDR_UNSPECIFIED
|
||||
#include <iphlpapi.h>
|
||||
|
||||
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char* iface/* unsupported */, uint32_t* ifIndex)
|
||||
bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char iface[IF_NAMESIZE + 1], uint32_t* ifIndex)
|
||||
{
|
||||
ULONG size = 0;
|
||||
if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
PMIB_IPFORWARD_TABLE2 pIpForwardTable = NULL;
|
||||
DWORD result = GetIpForwardTable2(AF_UNSPEC, &pIpForwardTable);
|
||||
|
||||
if (result != NO_ERROR)
|
||||
return false;
|
||||
|
||||
FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size);
|
||||
if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS)
|
||||
return false;
|
||||
bool foundDefault = false;
|
||||
|
||||
for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i)
|
||||
for (ULONG i = 0; i < pIpForwardTable->NumEntries; ++i)
|
||||
{
|
||||
MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i];
|
||||
if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0)
|
||||
MIB_IPFORWARD_ROW2* row = &pIpForwardTable->Table[i];
|
||||
|
||||
if ((row->DestinationPrefix.PrefixLength == 0) &&
|
||||
((row->DestinationPrefix.Prefix.Ipv4.sin_family == AF_INET &&
|
||||
row->DestinationPrefix.Prefix.Ipv4.sin_addr.S_un.S_addr == 0) ||
|
||||
(row->DestinationPrefix.Prefix.Ipv6.sin6_family == AF_INET6 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr))))
|
||||
{
|
||||
*ifIndex = ipForwardRow->dwForwardIfIndex;
|
||||
*ifIndex = row->InterfaceIndex;
|
||||
foundDefault = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
FreeMibTable(pIpForwardTable);
|
||||
|
||||
return foundDefault;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
#include <minwindef.h>
|
||||
#endif
|
||||
|
||||
struct addrinfo;
|
||||
|
||||
typedef struct FFNetworkingState {
|
||||
#ifdef _WIN32
|
||||
uintptr_t sockfd;
|
||||
OVERLAPPED overlapped;
|
||||
#else
|
||||
int sockfd;
|
||||
FFstrbuf host;
|
||||
FFstrbuf command;
|
||||
struct addrinfo* addr;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
FFThreadType thread;
|
||||
@@ -23,7 +25,14 @@ typedef struct FFNetworkingState {
|
||||
|
||||
uint32_t timeout;
|
||||
bool ipv6;
|
||||
bool compression; // if true, HTTP content compression will be enabled if supported
|
||||
bool tfo; // if true, TCP Fast Open will be attempted first, and fallback to traditional connection if it fails
|
||||
} FFNetworkingState;
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers);
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer);
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* ffNetworkingLoadZlibLibrary(void);
|
||||
bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd);
|
||||
#endif
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/library.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
#include <zlib.h>
|
||||
|
||||
struct FFZlibLibrary
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(inflateInit2_)
|
||||
FF_LIBRARY_SYMBOL(inflate)
|
||||
FF_LIBRARY_SYMBOL(inflateEnd)
|
||||
FF_LIBRARY_SYMBOL(inflateGetHeader)
|
||||
|
||||
bool inited;
|
||||
} zlibData;
|
||||
|
||||
const char* ffNetworkingLoadZlibLibrary(void)
|
||||
{
|
||||
if (!zlibData.inited)
|
||||
{
|
||||
zlibData.inited = true;
|
||||
FF_LIBRARY_LOAD(zlib, "dlopen libz failed",
|
||||
#ifdef _WIN32
|
||||
"zlib1"
|
||||
#else
|
||||
"libz"
|
||||
#endif
|
||||
FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateInit2_)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflate)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateEnd)
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlib, zlibData, inflateGetHeader)
|
||||
zlib = NULL; // don't auto dlclose
|
||||
}
|
||||
return zlibData.ffinflateEnd == NULL ? "Failed to load libz" : NULL;
|
||||
}
|
||||
|
||||
// Try to pre-read gzip header to determine uncompressed size
|
||||
static uint32_t guessGzipOutputSize(const void* data, uint32_t dataSize)
|
||||
{
|
||||
// gzip file format: http://www.zlib.org/rfc-gzip.html
|
||||
if (dataSize < 10 || ((const uint8_t*)data)[0] != 0x1f || ((const uint8_t*)data)[1] != 0x8b)
|
||||
return 0;
|
||||
|
||||
// Uncompressed size in gzip format is stored in the last 4 bytes, but only valid if data is less than 4GB
|
||||
if (dataSize > 18) {
|
||||
// Get ISIZE value from the end of file (little endian)
|
||||
const uint8_t* tail = (const uint8_t*)data + dataSize - 4;
|
||||
uint32_t uncompressedSize = (uint32_t) tail[0] | ((uint32_t) tail[1] << 8u) | ((uint32_t) tail[2] << 16u) | ((uint32_t) tail[3] << 24u);
|
||||
|
||||
// For valid gzip files, this value is the length of the uncompressed data modulo 2^32
|
||||
if (uncompressedSize > 0) {
|
||||
FF_DEBUG("Read uncompressed size from GZIP trailer: %u bytes", uncompressedSize);
|
||||
// Add some margin to the estimated size for safety
|
||||
return uncompressedSize + 64;
|
||||
}
|
||||
}
|
||||
|
||||
// If unable to get size from trailer or size is 0, use estimated value
|
||||
// Typically, text data compression ratio is between 3-5x, we use the larger value
|
||||
uint32_t estimatedSize = dataSize * 5;
|
||||
FF_DEBUG("Unable to read exact uncompressed size, estimated as 5x of compressed data: %u bytes", estimatedSize);
|
||||
return estimatedSize;
|
||||
}
|
||||
|
||||
// Decompress gzip content
|
||||
bool ffNetworkingDecompressGzip(FFstrbuf* buffer, char* headerEnd)
|
||||
{
|
||||
// Calculate header size
|
||||
uint32_t headerSize = (uint32_t) (headerEnd - buffer->chars);
|
||||
|
||||
*headerEnd = '\0'; // Replace delimiter with null character for easier processing
|
||||
// Ensure Content-Encoding is in response headers, not in response body
|
||||
bool hasGzip = strcasestr(buffer->chars, "\nContent-Encoding: gzip") != NULL;
|
||||
*headerEnd = '\r'; // Restore delimiter
|
||||
|
||||
if (!hasGzip) {
|
||||
FF_DEBUG("No gzip compressed content detected, skipping decompression");
|
||||
return true;
|
||||
}
|
||||
|
||||
FF_DEBUG("Gzip compressed content detected, preparing for decompression");
|
||||
|
||||
const char* bodyStart = headerEnd + 4; // Skip delimiter
|
||||
|
||||
// Calculate compressed content size
|
||||
uint32_t compressedSize = buffer->length - headerSize - 4;
|
||||
|
||||
if (compressedSize <= 0) {
|
||||
// No content to decompress
|
||||
FF_DEBUG("Compressed content size is 0, skipping decompression");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if content is actually in gzip format (gzip header magic is 0x1f 0x8b)
|
||||
if (compressedSize < 2 || (uint8_t)bodyStart[0] != 0x1f || (uint8_t)bodyStart[1] != 0x8b) {
|
||||
FF_DEBUG("Content is not valid gzip format, skipping decompression");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Predict uncompressed size
|
||||
uint32_t estimatedSize = guessGzipOutputSize(bodyStart, compressedSize);
|
||||
|
||||
// Create decompression buffer with estimated size
|
||||
FF_STRBUF_AUTO_DESTROY decompressedBuffer = ffStrbufCreateA(estimatedSize > 0 ? estimatedSize : compressedSize * 5);
|
||||
FF_DEBUG("Created decompression buffer: %u bytes", decompressedBuffer.allocated);
|
||||
|
||||
// Initialize decompression
|
||||
z_stream zs = {
|
||||
.zalloc = Z_NULL,
|
||||
.zfree = Z_NULL,
|
||||
.opaque = Z_NULL,
|
||||
.avail_in = (uInt)compressedSize,
|
||||
.next_in = (Bytef*)bodyStart,
|
||||
.avail_out = (uInt)ffStrbufGetFree(&decompressedBuffer),
|
||||
.next_out = (Bytef*)decompressedBuffer.chars,
|
||||
};
|
||||
|
||||
// Initialize decompression engine
|
||||
if (zlibData.ffinflateInit2_(&zs, 16 + MAX_WBITS, ZLIB_VERSION, (int)sizeof(z_stream)) != Z_OK) {
|
||||
FF_DEBUG("Failed to initialize decompression engine");
|
||||
return false;
|
||||
}
|
||||
uInt availableOut = zs.avail_out;
|
||||
|
||||
// Perform decompression
|
||||
int result = zlibData.ffinflate(&zs, Z_FINISH);
|
||||
|
||||
// If output buffer is insufficient, try to extend buffer
|
||||
while (result == Z_BUF_ERROR || (result != Z_STREAM_END && zs.avail_out == 0))
|
||||
{
|
||||
FF_DEBUG("Output buffer insufficient, trying to extend");
|
||||
|
||||
// Save already decompressed data amount
|
||||
uint32_t alreadyDecompressed = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += alreadyDecompressed;
|
||||
decompressedBuffer.chars[decompressedBuffer.length] = '\0'; // Ensure null-terminated string
|
||||
|
||||
ffStrbufEnsureFree(&decompressedBuffer, decompressedBuffer.length / 2);
|
||||
|
||||
// Set output parameters to point to new buffer
|
||||
zs.avail_out = (uInt)ffStrbufGetFree(&decompressedBuffer);
|
||||
zs.next_out = (Bytef*)(decompressedBuffer.chars + decompressedBuffer.length);
|
||||
availableOut = zs.avail_out;
|
||||
|
||||
// Decompress again
|
||||
result = zlibData.ffinflate(&zs, Z_FINISH);
|
||||
}
|
||||
|
||||
zlibData.ffinflateEnd(&zs);
|
||||
|
||||
// Calculate decompressed size
|
||||
uint32_t decompressedSize = (uint32_t)(availableOut - zs.avail_out);
|
||||
decompressedBuffer.length += decompressedSize;
|
||||
decompressedBuffer.chars[decompressedSize] = '\0'; // Ensure null-terminated string
|
||||
FF_DEBUG("Successfully decompressed %u bytes compressed data to %u bytes", compressedSize, decompressedBuffer.length);
|
||||
|
||||
// Modify Content-Length header and remove Content-Encoding header
|
||||
FF_STRBUF_AUTO_DESTROY newBuffer = ffStrbufCreateA(headerSize + decompressedSize + 64);
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, buffer))
|
||||
{
|
||||
if (ffStrStartsWithIgnCase(line, "Content-Encoding:"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (ffStrStartsWithIgnCase(line, "Content-Length:"))
|
||||
{
|
||||
ffStrbufAppendF(&newBuffer, "Content-Length: %u\r\n", decompressedSize);
|
||||
continue;
|
||||
}
|
||||
else if (line[0] == '\r')
|
||||
{
|
||||
ffStrbufAppendS(&newBuffer, "\r\n");
|
||||
ffStrbufGetlineRestore(&line, &len, buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&newBuffer, line);
|
||||
ffStrbufAppendC(&newBuffer, '\n');
|
||||
}
|
||||
|
||||
ffStrbufAppend(&newBuffer, &decompressedBuffer);
|
||||
ffStrbufDestroy(buffer);
|
||||
ffStrbufInitMove(buffer, &newBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // FF_HAVE_ZLIB
|
||||
@@ -0,0 +1,500 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "common/time.h"
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static const char* tryNonThreadingFastPath(FFNetworkingState* state)
|
||||
{
|
||||
#if defined(TCP_FASTOPEN) || __APPLE__
|
||||
|
||||
if (!state->tfo)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Linux doesn't support sendto() on unconnected sockets
|
||||
FF_DEBUG("TCP Fast Open disabled, skipping");
|
||||
return "TCP Fast Open disabled";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Attempting to use TCP Fast Open to connect");
|
||||
|
||||
#ifndef __APPLE__ // On macOS, TCP_FASTOPEN doesn't seem to be needed
|
||||
// Set TCP Fast Open
|
||||
#ifdef __linux__
|
||||
int flag = 5; // the queue length of pending packets
|
||||
#else
|
||||
int flag = 1; // enable TCP Fast Open
|
||||
#endif
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP,
|
||||
#ifdef __APPLE__
|
||||
// https://github.com/rust-lang/libc/pull/3135
|
||||
0x218 // TCP_FASTOPEN_FORCE_ENABLE
|
||||
#else
|
||||
TCP_FASTOPEN
|
||||
#endif
|
||||
, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_FASTOPEN option: %s", strerror(errno));
|
||||
return "setsockopt(TCP_FASTOPEN) failed";
|
||||
} else {
|
||||
#ifdef __linux__
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option, queue length: %d", flag);
|
||||
#elif defined(__APPLE__)
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN_FORCE_ENABLE option");
|
||||
#else
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
FF_DEBUG("Using sendto() + MSG_DONTWAIT to send %u bytes of data", state->command.length);
|
||||
ssize_t sent = sendto(state->sockfd,
|
||||
state->command.chars,
|
||||
state->command.length,
|
||||
#ifdef MSG_FASTOPEN
|
||||
MSG_FASTOPEN |
|
||||
#endif
|
||||
#ifdef MSG_NOSIGNAL
|
||||
MSG_NOSIGNAL |
|
||||
#endif
|
||||
MSG_DONTWAIT,
|
||||
state->addr->ai_addr,
|
||||
state->addr->ai_addrlen);
|
||||
#else
|
||||
if (fcntl(state->sockfd, F_SETFL, O_NONBLOCK) == -1) {
|
||||
FF_DEBUG("fcntl(F_SETFL) failed: %s", strerror(errno));
|
||||
return "fcntl(F_SETFL) failed";
|
||||
}
|
||||
FF_DEBUG("Using connectx() to send %u bytes of data", state->command.length);
|
||||
// Use connectx to establish connection and send data in one call
|
||||
size_t sent;
|
||||
if (connectx(state->sockfd,
|
||||
&(sa_endpoints_t) {
|
||||
.sae_dstaddr = state->addr->ai_addr,
|
||||
.sae_dstaddrlen = state->addr->ai_addrlen,
|
||||
},
|
||||
SAE_ASSOCID_ANY, state->tfo ? CONNECT_DATA_IDEMPOTENT : 0,
|
||||
&(struct iovec) {
|
||||
.iov_base = state->command.chars,
|
||||
.iov_len = state->command.length,
|
||||
}, 1, &sent, NULL) != 0) sent = 0;
|
||||
if (fcntl(state->sockfd, F_SETFL, 0) == -1) {
|
||||
FF_DEBUG("fcntl(F_SETFL) failed: %s", strerror(errno));
|
||||
return "fcntl(F_SETFL) failed";
|
||||
}
|
||||
#endif
|
||||
if (sent > 0 || (errno == EAGAIN || errno == EWOULDBLOCK
|
||||
#ifdef __APPLE__
|
||||
// On macOS EINPROGRESS means the connection cannot be completed immediately
|
||||
// On Linux, it means the TFO cookie is not available locally
|
||||
|| errno == EINPROGRESS
|
||||
#endif
|
||||
))
|
||||
{
|
||||
FF_DEBUG(
|
||||
#ifdef __APPLE__
|
||||
"connectx()"
|
||||
#else
|
||||
"sendto()"
|
||||
#endif
|
||||
" %s (sent=%zd, errno=%d: %s)", errno == 0 ? "succeeded" : "was in progress",
|
||||
sent, errno, strerror(errno));
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
ffStrbufDestroy(&state->command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_DEBUG(
|
||||
#ifdef __APPLE__
|
||||
"connectx()"
|
||||
#else
|
||||
"sendto()"
|
||||
#endif
|
||||
" failed: %s (errno=%d)", strerror(errno), errno);
|
||||
#ifdef __APPLE__
|
||||
return "connectx() failed";
|
||||
#else
|
||||
return "sendto() failed";
|
||||
#endif
|
||||
#else
|
||||
FF_UNUSED(state);
|
||||
return "TFO support is not available";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Traditional connect and send function
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
const char* ret = NULL;
|
||||
FF_DEBUG("Using traditional connection method to connect");
|
||||
|
||||
FF_DEBUG("Attempting connect() to server...");
|
||||
if(connect(state->sockfd, state->addr->ai_addr, state->addr->ai_addrlen) == -1)
|
||||
{
|
||||
FF_DEBUG("connect() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("connect() succeeded");
|
||||
|
||||
FF_DEBUG("Attempting to send %u bytes of data...", state->command.length);
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
FF_DEBUG("send() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Data sent successfully");
|
||||
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
FF_DEBUG("Error occurred, closing socket");
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
|
||||
exit:
|
||||
FF_DEBUG("Releasing address info and other resources");
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
// Parallel DNS resolution and socket creation
|
||||
static const char* initNetworkingState(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Initializing network connection state: host=%s, path=%s", host, path);
|
||||
|
||||
// Initialize command and host information
|
||||
ffStrbufInitA(&state->command, 64);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
// Add extra optimized HTTP headers
|
||||
ffStrbufAppendS(&state->command, "Connection: close\r\n"); // Explicitly tell the server we don't need to keep the connection
|
||||
|
||||
// If compression needs to be enabled
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Enabling HTTP content compression");
|
||||
ffStrbufAppendS(&state->command, "Accept-Encoding: gzip\r\n");
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&state->command, headers);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
state->thread = 0;
|
||||
FF_DEBUG("Thread ID initialized to 0");
|
||||
#endif
|
||||
|
||||
const char* ret = NULL;
|
||||
|
||||
struct addrinfo hints = {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_NUMERICSERV
|
||||
};
|
||||
|
||||
FF_DEBUG("Resolving address: %s (%s)", host, state->ipv6 ? "IPv6" : "IPv4");
|
||||
// Use AI_NUMERICSERV flag to indicate the service is a numeric port, reducing parsing time
|
||||
|
||||
if(getaddrinfo(host, "80", &hints, &state->addr) != 0)
|
||||
{
|
||||
FF_DEBUG("getaddrinfo() failed: %s", gai_strerror(errno));
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Address resolution successful");
|
||||
|
||||
FF_DEBUG("Creating socket");
|
||||
state->sockfd = socket(state->addr->ai_family, state->addr->ai_socktype, state->addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
FF_DEBUG("socket() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
FF_DEBUG("Socket creation successful: fd=%d", state->sockfd);
|
||||
|
||||
int flag = 1;
|
||||
#ifdef TCP_NODELAY
|
||||
// Disable Nagle's algorithm to reduce small packet transmission delay
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_NODELAY: %s", strerror(errno));
|
||||
} else {
|
||||
FF_DEBUG("Successfully disabled Nagle's algorithm");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TCP_QUICKACK
|
||||
// Set TCP_QUICKACK option to avoid delayed acknowledgments
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_QUICKACK, &flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_QUICKACK: %s", strerror(errno));
|
||||
} else {
|
||||
FF_DEBUG("Successfully enabled TCP quick acknowledgment");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting connection timeout: %u ms", state->timeout);
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
FF_DEBUG("Using TCP_CONNECTIONTIMEOUT: %u seconds", sec);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
FF_DEBUG("Using TCP_KEEPINIT: %u seconds", sec);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
FF_DEBUG("Using TCP_USER_TIMEOUT: %u milliseconds", state->timeout);
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#else
|
||||
FF_DEBUG("Current platform does not support TCP connection timeout");
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
FF_DEBUG("Error occurred during initialization");
|
||||
if (state->addr != NULL)
|
||||
{
|
||||
FF_DEBUG("Releasing address information");
|
||||
freeaddrinfo(state->addr);
|
||||
state->addr = NULL;
|
||||
}
|
||||
|
||||
if (state->sockfd > 0)
|
||||
{
|
||||
FF_DEBUG("Closing socket: fd=%d", state->sockfd);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Preparing to send HTTP request: host=%s, path=%s", host, path);
|
||||
|
||||
if (state->compression)
|
||||
{
|
||||
FF_DEBUG("Compression enabled, checking if zlib is available");
|
||||
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* zlibError = ffNetworkingLoadZlibLibrary();
|
||||
// Only enable compression if zlib library is successfully loaded
|
||||
if (zlibError == NULL)
|
||||
{
|
||||
FF_DEBUG("Successfully loaded zlib library, compression enabled");
|
||||
} else {
|
||||
FF_DEBUG("Failed to load zlib library, compression disabled: %s", zlibError);
|
||||
state->compression = false;
|
||||
}
|
||||
#else
|
||||
FF_DEBUG("zlib not supported at build time, compression disabled");
|
||||
state->compression = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Compression disabled");
|
||||
}
|
||||
|
||||
const char* initResult = initNetworkingState(state, host, path, headers);
|
||||
if (initResult != NULL) {
|
||||
FF_DEBUG("Initialization failed: %s", initResult);
|
||||
return initResult;
|
||||
}
|
||||
FF_DEBUG("Network state initialization successful");
|
||||
|
||||
const char* tfoResult = tryNonThreadingFastPath(state);
|
||||
if (tfoResult == NULL) {
|
||||
FF_DEBUG("TryNonThreadingFastPath() succeeded or in progress");
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("TryNonThreadingFastPath() failed: %s, trying traditional connection", tfoResult);
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
FF_DEBUG("Multithreading mode enabled, creating connection thread");
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
if (state->thread) {
|
||||
FF_DEBUG("Thread creation successful: thread=%p", (void*)state->thread);
|
||||
return NULL;
|
||||
}
|
||||
FF_DEBUG("Thread creation failed");
|
||||
} else {
|
||||
FF_DEBUG("Multithreading mode disabled, connecting in main thread");
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (state->thread)
|
||||
{
|
||||
FF_DEBUG("Connection thread is running, waiting for it to complete (timeout=%u ms)", timeout);
|
||||
if (!ffThreadJoin(state->thread, timeout)) {
|
||||
FF_DEBUG("Thread join failed or timed out");
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
FF_DEBUG("Thread completed successfully");
|
||||
state->thread = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
FF_DEBUG("Invalid socket, HTTP request might have failed");
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
}
|
||||
|
||||
// Set larger initial receive buffer instead of small repeated receives
|
||||
int rcvbuf = 65536; // 64KB
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
|
||||
|
||||
#ifdef __APPLE__
|
||||
// poll for the socket to be readable.
|
||||
// Because of the non-blocking connectx() call, the connection might not be established yet
|
||||
FF_DEBUG("Using poll() to check if socket is readable");
|
||||
if (poll(&(struct pollfd) {
|
||||
.fd = state->sockfd,
|
||||
.events = POLLIN
|
||||
}, 1, timeout > 0 ? (int) timeout : -1) == -1)
|
||||
{
|
||||
FF_DEBUG("poll() failed: %s (errno=%d)", strerror(errno), errno);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
return "poll() failed";
|
||||
}
|
||||
FF_DEBUG("Socket is readable, proceeding to receive data");
|
||||
#else
|
||||
if(timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting receive timeout: %u ms", timeout);
|
||||
struct timeval timev;
|
||||
timev.tv_sec = timeout / 1000;
|
||||
timev.tv_usec = (__typeof__(timev.tv_usec)) ((timeout % 1000) * 1000); //milliseconds to microseconds
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
++recvCount, buffer->length, ffStrbufGetFree(buffer));
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), MSG_WAITALL);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received == 0) {
|
||||
FF_DEBUG("Connection closed (received=0)");
|
||||
} else {
|
||||
FF_DEBUG("Reception failed: %s (errno=%d)", strerror(errno), errno);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = memmem(buffer->chars, buffer->length, "\r\n\r\n", 4);
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
if (clHeader) {
|
||||
contentLength = (uint32_t) strtoul(clHeader + 16, NULL, 10);
|
||||
if (contentLength > 0) {
|
||||
FF_DEBUG("Detected Content-Length: %u, pre-allocating buffer", contentLength);
|
||||
// Ensure buffer is large enough, adding header size and some margin
|
||||
ffStrbufEnsureFree(buffer, contentLength + 16);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0);
|
||||
|
||||
FF_DEBUG("Closing socket: fd=%d", state->sockfd);
|
||||
close(state->sockfd);
|
||||
state->sockfd = -1;
|
||||
|
||||
if (buffer->length == 0) {
|
||||
FF_DEBUG("Server response is empty");
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
if (contentLength > 0 && buffer->length != contentLength + (uint32_t)(headerEnd - buffer->chars) + 4) {
|
||||
FF_DEBUG("Received content length mismatches: %u != %u", buffer->length, contentLength + (uint32_t)(headerEnd - buffer->chars) + 4);
|
||||
return "Content length mismatch";
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
|
||||
FF_DEBUG("Received valid HTTP 200 response, content %u bytes, total %u bytes", contentLength, buffer->length);
|
||||
} else {
|
||||
FF_DEBUG("Invalid response: %.40s...", buffer->chars);
|
||||
return "Invalid response";
|
||||
}
|
||||
|
||||
// If compression was used, try to decompress
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
FF_DEBUG("Decompression successful or no decompression needed, total length after decompression: %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
//Must be included after <mswsock.h>
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking/networking.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/debug.h"
|
||||
|
||||
static LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
static const char* initWsaData(WSADATA* wsaData)
|
||||
{
|
||||
FF_DEBUG("Initializing WinSock");
|
||||
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0) {
|
||||
FF_DEBUG("WSAStartup() failed");
|
||||
return "WSAStartup() failed";
|
||||
}
|
||||
|
||||
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2) {
|
||||
FF_DEBUG("Invalid wsaData version found: %d.%d", LOBYTE(wsaData->wVersion), HIBYTE(wsaData->wVersion));
|
||||
return "Invalid wsaData version found";
|
||||
}
|
||||
|
||||
//Dummy socket needed for WSAIoctl
|
||||
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd == INVALID_SOCKET) {
|
||||
FF_DEBUG("socket(AF_INET, SOCK_STREAM) failed");
|
||||
return "socket(AF_INET, SOCK_STREAM) failed";
|
||||
}
|
||||
|
||||
DWORD dwBytes;
|
||||
GUID guid = WSAID_CONNECTEX;
|
||||
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&guid, sizeof(guid),
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&dwBytes, NULL, NULL) != 0) {
|
||||
FF_DEBUG("WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed");
|
||||
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
|
||||
}
|
||||
|
||||
closesocket(sockfd);
|
||||
FF_DEBUG("WinSock initialized successfully");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
FF_DEBUG("Preparing to send HTTP request: host=%s, path=%s", host, path);
|
||||
|
||||
if (state->compression)
|
||||
{
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
const char* zlibError = ffNetworkingLoadZlibLibrary();
|
||||
// Only enable compression if zlib library is successfully loaded
|
||||
if (zlibError == NULL)
|
||||
{
|
||||
FF_DEBUG("Successfully loaded zlib library, compression enabled");
|
||||
} else {
|
||||
FF_DEBUG("Failed to load zlib library, compression disabled: %s", zlibError);
|
||||
state->compression = false;
|
||||
}
|
||||
#else
|
||||
FF_DEBUG("zlib not supported at build time, compression disabled");
|
||||
state->compression = false;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("Compression disabled");
|
||||
}
|
||||
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
FF_DEBUG("WinSock initialization failed: %s", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
{
|
||||
FF_DEBUG("WinSock initialization previously failed");
|
||||
return "initWsaData() failed before";
|
||||
}
|
||||
|
||||
struct addrinfo* addr;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_flags = AI_NUMERICSERV,
|
||||
};
|
||||
|
||||
FF_DEBUG("Resolving address: %s (%s)", host, state->ipv6 ? "IPv6" : "IPv4");
|
||||
if(getaddrinfo(host, "80", &hints, &addr) != 0)
|
||||
{
|
||||
FF_DEBUG("getaddrinfo() failed");
|
||||
return "getaddrinfo() failed";
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
FF_DEBUG("socket() failed");
|
||||
freeaddrinfo(addr);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
DWORD flag = 1;
|
||||
#ifdef TCP_NODELAY
|
||||
// Enable TCP_NODELAY to disable Nagle's algorithm
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_NODELAY: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
} else {
|
||||
FF_DEBUG("Successfully disabled Nagle's algorithm");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set timeout if needed
|
||||
if (state->timeout > 0) {
|
||||
FF_DEBUG("Setting connection timeout: %u ms", state->timeout);
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&state->timeout, sizeof(state->timeout));
|
||||
}
|
||||
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if((state->ipv6
|
||||
? bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = in6addr_any,
|
||||
}, sizeof(struct sockaddr_in6))
|
||||
: bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
}, sizeof(struct sockaddr_in))) != 0)
|
||||
{
|
||||
FF_DEBUG("bind() failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
// Initialize overlapped structure for asynchronous I/O
|
||||
memset(&state->overlapped, 0, sizeof(OVERLAPPED));
|
||||
|
||||
// Build HTTP command
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.0\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&command, "Connection: close\r\n"); // Explicitly request connection closure
|
||||
|
||||
// Add compression support if enabled
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Enabling HTTP content compression");
|
||||
ffStrbufAppendS(&command, "Accept-Encoding: gzip\r\n");
|
||||
}
|
||||
|
||||
ffStrbufAppendS(&command, headers);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
|
||||
#ifdef TCP_FASTOPEN
|
||||
if (state->tfo)
|
||||
{
|
||||
// Set TCP Fast Open
|
||||
flag = 1;
|
||||
if (setsockopt(state->sockfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&flag, sizeof(flag)) != 0) {
|
||||
FF_DEBUG("Failed to set TCP_FASTOPEN option: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
} else {
|
||||
FF_DEBUG("Successfully set TCP_FASTOPEN option");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("TCP Fast Open disabled");
|
||||
}
|
||||
#endif
|
||||
|
||||
FF_DEBUG("Using ConnectEx to send %u bytes of data", command.length);
|
||||
DWORD sent = 0;
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen,
|
||||
command.chars, command.length, &sent, &state->overlapped);
|
||||
|
||||
freeaddrinfo(addr);
|
||||
addr = NULL;
|
||||
|
||||
if(!result)
|
||||
{
|
||||
if (WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
FF_DEBUG("ConnectEx() failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("ConnectEx() pending");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_DEBUG("ConnectEx() succeeded, sent %u bytes of data", (unsigned) sent);
|
||||
}
|
||||
|
||||
// No need to cleanup state fields here since we need them in the receive function
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
FF_DEBUG("Preparing to receive HTTP response");
|
||||
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
FF_DEBUG("Invalid socket, HTTP request might have failed");
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
}
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject with timeout: %u ms", timeout);
|
||||
if (WaitForSingleObject((HANDLE)state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
FF_DEBUG("WaitForSingleObject failed or timed out");
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
FF_DEBUG("WSAGetOverlappedResult failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
closesocket(state->sockfd);
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
FF_DEBUG("Setting receive timeout: %u ms", timeout);
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
// Set larger receive buffer for better performance
|
||||
int rcvbuf = 65536; // 64KB
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVBUF, (const char*)&rcvbuf, sizeof(rcvbuf));
|
||||
|
||||
FF_DEBUG("Starting data reception");
|
||||
FF_MAYBE_UNUSED int recvCount = 0;
|
||||
uint32_t contentLength = 0;
|
||||
char* headerEnd = NULL;
|
||||
|
||||
do {
|
||||
FF_DEBUG("Data reception loop #%d, current buffer size: %u, available space: %u",
|
||||
++recvCount, buffer->length, ffStrbufGetFree(buffer));
|
||||
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int)ffStrbufGetFree(buffer), 0);
|
||||
|
||||
if (received <= 0) {
|
||||
if (received == 0) {
|
||||
FF_DEBUG("Connection closed (received=0)");
|
||||
} else {
|
||||
FF_DEBUG("Reception failed: %s", ffDebugWin32Error((DWORD) WSAGetLastError()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
|
||||
FF_DEBUG("Successfully received %zd bytes of data, total: %u bytes", received, buffer->length);
|
||||
|
||||
// Check if HTTP header end marker is found
|
||||
if (headerEnd == NULL) {
|
||||
headerEnd = strstr(buffer->chars, "\r\n\r\n");
|
||||
if (headerEnd != NULL) {
|
||||
FF_DEBUG("Found HTTP header end marker, position: %ld", (long)(headerEnd - buffer->chars));
|
||||
|
||||
// Check for Content-Length header to pre-allocate enough memory
|
||||
const char* clHeader = strcasestr(buffer->chars, "Content-Length:");
|
||||
if (clHeader) {
|
||||
contentLength = (uint32_t) strtoul(clHeader + 16, NULL, 10);
|
||||
if (contentLength > 0) {
|
||||
FF_DEBUG("Detected Content-Length: %u, pre-allocating buffer", contentLength);
|
||||
// Ensure buffer is large enough, adding header size and some margin
|
||||
ffStrbufEnsureFree(buffer, contentLength + 16);
|
||||
FF_DEBUG("Extended receive buffer to %u bytes", buffer->allocated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (ffStrbufGetFree(buffer) > 0);
|
||||
|
||||
FF_DEBUG("Closing socket: fd=%u", (unsigned)state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
|
||||
if (buffer->length == 0) {
|
||||
FF_DEBUG("Server response is empty");
|
||||
return "Empty server response received";
|
||||
}
|
||||
|
||||
if (headerEnd == NULL) {
|
||||
FF_DEBUG("No HTTP header end marker found");
|
||||
return "No HTTP header end found";
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(buffer, "HTTP/1.0 200 OK\r\n")) {
|
||||
FF_DEBUG("Received valid HTTP 200 response, content length: %u bytes, total length: %u bytes",
|
||||
contentLength, buffer->length);
|
||||
} else {
|
||||
FF_DEBUG("Invalid response: %.40s...", buffer->chars);
|
||||
return "Invalid response";
|
||||
}
|
||||
|
||||
// If compression was used, try to decompress
|
||||
#ifdef FF_HAVE_ZLIB
|
||||
if (state->compression) {
|
||||
FF_DEBUG("Content received, checking if compressed");
|
||||
if (!ffNetworkingDecompressGzip(buffer, headerEnd)) {
|
||||
FF_DEBUG("Decompression failed or invalid compression format");
|
||||
return "Failed to decompress or invalid format";
|
||||
} else {
|
||||
FF_DEBUG("Decompression successful or no decompression needed, total length after decompression: %u bytes", buffer->length);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // For FreeBSD
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
static const char* connectAndSend(FFNetworkingState* state)
|
||||
{
|
||||
const char* ret = NULL;
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(state->host.chars, "80", &(struct addrinfo) {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
{
|
||||
ret = "getaddrinfo() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == -1)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
ret = "socket() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (state->timeout > 0)
|
||||
{
|
||||
FF_MAYBE_UNUSED uint32_t sec = state->timeout / 1000;
|
||||
if (sec == 0) sec = 1;
|
||||
|
||||
#ifdef TCP_CONNECTIONTIMEOUT
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_CONNECTIONTIMEOUT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_KEEPINIT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_KEEPINIT, &sec, sizeof(sec));
|
||||
#elif defined(TCP_USER_TIMEOUT)
|
||||
setsockopt(state->sockfd, IPPROTO_TCP, TCP_USER_TIMEOUT, &state->timeout, sizeof(state->timeout));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(connect(state->sockfd, addr->ai_addr, addr->ai_addrlen) == -1)
|
||||
{
|
||||
close(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
ret = "connect() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
freeaddrinfo(addr);
|
||||
|
||||
if(send(state->sockfd, state->command.chars, state->command.length, 0) < 0)
|
||||
{
|
||||
close(state->sockfd);
|
||||
ret = "send() failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
error:
|
||||
state->sockfd = -1;
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&state->host);
|
||||
ffStrbufDestroy(&state->command);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FF_THREAD_ENTRY_DECL_WRAPPER(connectAndSend, FFNetworkingState*);
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
ffStrbufInitS(&state->host, host);
|
||||
|
||||
ffStrbufInitA(&state->command, 64);
|
||||
ffStrbufAppendS(&state->command, "GET ");
|
||||
ffStrbufAppendS(&state->command, path);
|
||||
ffStrbufAppendS(&state->command, " HTTP/1.1\nHost: ");
|
||||
ffStrbufAppendS(&state->command, host);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
ffStrbufAppendS(&state->command, headers);
|
||||
ffStrbufAppendS(&state->command, "\r\n");
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
state->thread = ffThreadCreate(connectAndSendThreadMain, state);
|
||||
return state->thread ? NULL : "ffThreadCreate(connectAndSend) failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
return connectAndSend(state);
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t timeout = state->timeout;
|
||||
|
||||
#ifdef FF_HAVE_THREADS
|
||||
if (instance.config.general.multithreading)
|
||||
{
|
||||
if (!ffThreadJoin(state->thread, timeout))
|
||||
return "ffThreadJoin() failed or timeout";
|
||||
}
|
||||
#endif
|
||||
|
||||
if(state->sockfd == -1)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
struct timeval timev;
|
||||
timev.tv_sec = timeout / 1000;
|
||||
timev.tv_usec = (__typeof__(timev.tv_usec)) ((timeout % 1000) * 1000); //milliseconds to microseconds
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev));
|
||||
}
|
||||
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length += (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
close(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
#include <mswsock.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
//Must be included after <mswsock.h>
|
||||
#include "fastfetch.h"
|
||||
#include "common/networking.h"
|
||||
|
||||
static LPFN_CONNECTEX ConnectEx;
|
||||
|
||||
static const char* initWsaData(WSADATA* wsaData)
|
||||
{
|
||||
if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0)
|
||||
return "WSAStartup() failed";
|
||||
|
||||
if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2)
|
||||
return "Invalid wsaData version found";
|
||||
|
||||
//Dummy socket needed for WSAIoctl
|
||||
SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sockfd == INVALID_SOCKET)
|
||||
return "socket(AF_INET, SOCK_STREAM) failed";
|
||||
|
||||
DWORD dwBytes;
|
||||
GUID guid = WSAID_CONNECTEX;
|
||||
if(WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER,
|
||||
&guid, sizeof(guid),
|
||||
&ConnectEx, sizeof(ConnectEx),
|
||||
&dwBytes, NULL, NULL) != 0)
|
||||
return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed";
|
||||
|
||||
closesocket(sockfd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers)
|
||||
{
|
||||
static WSADATA wsaData;
|
||||
if (wsaData.wVersion == 0)
|
||||
{
|
||||
const char* error = initWsaData(&wsaData);
|
||||
if (error != NULL)
|
||||
{
|
||||
wsaData.wVersion = (WORD) -1;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else if (wsaData.wVersion == (WORD) -1)
|
||||
return "initWsaData() failed before";
|
||||
|
||||
struct addrinfo* addr;
|
||||
|
||||
if(getaddrinfo(host, "80", &(struct addrinfo) {
|
||||
.ai_family = state->ipv6 ? AF_INET6 : AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
}, &addr) != 0)
|
||||
return "getaddrinfo() failed";
|
||||
|
||||
state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||
if(state->sockfd == INVALID_SOCKET)
|
||||
{
|
||||
freeaddrinfo(addr);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
//ConnectEx requires the socket to be initially bound
|
||||
if((state->ipv6
|
||||
? bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in6) {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = in6addr_any,
|
||||
}, sizeof(struct sockaddr_in6))
|
||||
: bind(state->sockfd, (SOCKADDR *) &(struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
}, sizeof(struct sockaddr_in))) != 0)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
freeaddrinfo(addr);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "bind() failed";
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY command = ffStrbufCreateA(64);
|
||||
ffStrbufAppendS(&command, "GET ");
|
||||
ffStrbufAppendS(&command, path);
|
||||
ffStrbufAppendS(&command, " HTTP/1.1\nHost: ");
|
||||
ffStrbufAppendS(&command, host);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
ffStrbufAppendS(&command, headers);
|
||||
ffStrbufAppendS(&command, "\r\n");
|
||||
|
||||
BOOL result = ConnectEx(state->sockfd, addr->ai_addr, (int)addr->ai_addrlen, command.chars, command.length, NULL, &state->overlapped);
|
||||
freeaddrinfo(addr);
|
||||
|
||||
if(!result && WSAGetLastError() != WSA_IO_PENDING)
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
state->sockfd = INVALID_SOCKET;
|
||||
return "ConnectEx() failed";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer)
|
||||
{
|
||||
if (state->sockfd == INVALID_SOCKET)
|
||||
return "ffNetworkingSendHttpRequest() failed";
|
||||
|
||||
uint32_t timeout = state->timeout;
|
||||
if (timeout > 0)
|
||||
{
|
||||
if (WaitForSingleObject((HANDLE) state->sockfd, timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo((HANDLE) state->sockfd);
|
||||
closesocket(state->sockfd);
|
||||
return "WaitForSingleObject(state->sockfd) failed or timeout";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD transfer, flags;
|
||||
if (!WSAGetOverlappedResult(state->sockfd, &state->overlapped, &transfer, TRUE, &flags))
|
||||
{
|
||||
closesocket(state->sockfd);
|
||||
return "WSAGetOverlappedResult() failed";
|
||||
}
|
||||
|
||||
if(timeout > 0)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-setsockopt
|
||||
setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
uint32_t recvStart;
|
||||
do {
|
||||
recvStart = buffer->length;
|
||||
ssize_t received = recv(state->sockfd, buffer->chars + buffer->length, (int) ffStrbufGetFree(buffer), 0);
|
||||
if (received <= 0) break;
|
||||
buffer->length = recvStart + (uint32_t) received;
|
||||
buffer->chars[buffer->length] = '\0';
|
||||
} while (ffStrbufGetFree(buffer) > 0 && strstr(buffer->chars + recvStart, "\r\n\r\n") == NULL);
|
||||
|
||||
closesocket(state->sockfd);
|
||||
if (buffer->length == 0) return "Empty server response received";
|
||||
return ffStrbufStartsWithS(buffer, "HTTP/1.1 200 OK\r\n") ? NULL : "Invalid response";
|
||||
}
|
||||
@@ -177,6 +177,7 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
if (ffCharIsEnglishAlphabet(value[0]))
|
||||
{
|
||||
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
|
||||
else FF_APPEND_COLOR_CODE_COND(bold_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(dim_, FF_COLOR_MODE_DIM)
|
||||
else FF_APPEND_COLOR_CODE_COND(italic_, FF_COLOR_MODE_ITALIC)
|
||||
@@ -212,6 +213,35 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
exit(479);
|
||||
}
|
||||
}
|
||||
else if (value[0] == '#')
|
||||
{
|
||||
// RGB color
|
||||
++value;
|
||||
char* pend = NULL;
|
||||
uint32_t rgb = (uint32_t) strtoul(value, &pend, 16);
|
||||
if (pend == value) {
|
||||
fprintf(stderr, "Error: invalid RGB color code found: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
if (pend - value > 6) {
|
||||
fprintf(stderr, "Error: RGB color code too long: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
else if (pend - value == 3) {
|
||||
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
|
||||
((rgb & 0x0F0) >> 4) * 0x001100 +
|
||||
((rgb & 0x00F) >> 0) * 0x000011;
|
||||
}
|
||||
else if (pend - value != 6) {
|
||||
fprintf(stderr, "Error: invalid RGB color code length: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
|
||||
uint32_t r = rgb >> 16, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
|
||||
ffStrbufAppendF(buffer, FF_COLOR_FG_RGB "%u;%u;%u", r, g, b);
|
||||
value = pend;
|
||||
continue;
|
||||
}
|
||||
ffStrbufAppendC(buffer, *value);
|
||||
++value;
|
||||
|
||||
|
||||
+16
-3
@@ -190,14 +190,27 @@ 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)
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result)
|
||||
{
|
||||
if(days == 0 && hours == 0 && minutes == 0)
|
||||
if(totalSeconds < 60)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u seconds", seconds);
|
||||
ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds);
|
||||
if (totalSeconds != 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t seconds = (uint32_t) (totalSeconds % 60);
|
||||
totalSeconds /= 60;
|
||||
if (seconds >= 30)
|
||||
totalSeconds++;
|
||||
|
||||
uint32_t minutes = (uint32_t) (totalSeconds % 60);
|
||||
totalSeconds /= 60;
|
||||
uint32_t hours = (uint32_t) (totalSeconds % 24);
|
||||
totalSeconds /= 24;
|
||||
uint32_t days = (uint32_t) totalSeconds;
|
||||
|
||||
if(days > 0)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u day", days);
|
||||
|
||||
@@ -27,4 +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);
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "logo/logo.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType)
|
||||
@@ -99,7 +100,7 @@ void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleAr
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
if(!instance.config.display.showErrors)
|
||||
return;
|
||||
@@ -109,7 +110,10 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
vprintf(message, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
@@ -117,14 +121,6 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, moduleArgs, printType, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
void ffPrintColor(const FFstrbuf* colorValue)
|
||||
{
|
||||
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||
|
||||
+144
-17
@@ -12,6 +12,10 @@
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if !(__ANDROID__ || __OpenBSD__)
|
||||
#include <spawn.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
@@ -28,13 +32,20 @@
|
||||
#elif defined(__NetBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
#endif
|
||||
|
||||
#ifndef environ
|
||||
extern char** environ;
|
||||
#endif
|
||||
|
||||
enum { FF_PIPE_BUFSIZ = 8192 };
|
||||
|
||||
static inline int ffPipe2(int *fds, int flags)
|
||||
static inline int ffPipe2(int* fds, int flags)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
#ifndef FF_HAVE_PIPE2
|
||||
if(pipe(fds) == -1)
|
||||
return -1;
|
||||
fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | flags);
|
||||
@@ -45,6 +56,8 @@ static inline int ffPipe2(int *fds, int flags)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Not thread-safe
|
||||
const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr)
|
||||
{
|
||||
int pipes[2];
|
||||
@@ -53,7 +66,77 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if(ffPipe2(pipes, O_CLOEXEC) == -1)
|
||||
return "pipe() failed";
|
||||
|
||||
pid_t childPid = fork();
|
||||
pid_t childPid = -1;
|
||||
int nullFile = ffGetNullFD();
|
||||
|
||||
#if !(__ANDROID__ || __OpenBSD__)
|
||||
|
||||
// NetBSD / Darwin: native syscall
|
||||
// Linux (glibc): clone3-execve
|
||||
// FreeBSD: vfork-execve
|
||||
// illumos: vforkx-execve
|
||||
// OpenBSD / Android (bionic): fork-execve
|
||||
|
||||
posix_spawn_file_actions_t file_actions;
|
||||
posix_spawn_file_actions_init(&file_actions);
|
||||
posix_spawn_file_actions_adddup2(&file_actions, pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
posix_spawn_file_actions_adddup2(&file_actions, nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
|
||||
static char* oldLang = NULL;
|
||||
static int langIndex = -1;
|
||||
|
||||
if (langIndex >= 0)
|
||||
{
|
||||
// Found before
|
||||
if (oldLang) // oldLang was set only if it needed to be changed
|
||||
{
|
||||
if (environ[langIndex] != oldLang)
|
||||
{
|
||||
// environ is changed outside of this function
|
||||
langIndex = -1;
|
||||
}
|
||||
else
|
||||
environ[langIndex] = (char*) "LANG=C.UTF-8";
|
||||
}
|
||||
}
|
||||
if (langIndex < 0)
|
||||
{
|
||||
for (int i = 0; environ[i] != NULL; i++)
|
||||
{
|
||||
if (ffStrStartsWith(environ[i], "LANG="))
|
||||
{
|
||||
langIndex = i;
|
||||
const char* langValue = environ[i] + 5; // Skip "LANG="
|
||||
if (ffStrEqualsIgnCase(langValue, "C") ||
|
||||
ffStrStartsWithIgnCase(environ[i], "C.") ||
|
||||
ffStrEqualsIgnCase(langValue, "en_US") ||
|
||||
ffStrStartsWithIgnCase(langValue, "en_US."))
|
||||
break; // No need to change LANG
|
||||
oldLang = environ[i];
|
||||
environ[i] = (char*) "LANG=C.UTF-8"; // Set LANG to C.UTF-8 for consistent output
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ret = posix_spawnp(&childPid, argv[0], &file_actions, NULL, argv, environ);
|
||||
|
||||
if (oldLang)
|
||||
environ[langIndex] = oldLang;
|
||||
|
||||
posix_spawn_file_actions_destroy(&file_actions);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
return "posix_spawnp() failed";
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// https://github.com/termux/termux-packages/issues/25369
|
||||
childPid = fork();
|
||||
if(childPid == -1)
|
||||
{
|
||||
close(pipes[0]);
|
||||
@@ -61,18 +144,18 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
return "fork() failed";
|
||||
}
|
||||
|
||||
//Child
|
||||
if(childPid == 0)
|
||||
{
|
||||
int nullFile = open("/dev/null", O_WRONLY | O_CLOEXEC);
|
||||
//Child
|
||||
dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO);
|
||||
dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO);
|
||||
setenv("LANG", "C", 1);
|
||||
putenv("LANG=C.UTF-8");
|
||||
execvp(argv[0], argv);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
//Parent
|
||||
#endif
|
||||
|
||||
close(pipes[1]);
|
||||
|
||||
int FF_AUTO_CLOSE_FD childPipeFd = pipes[0];
|
||||
@@ -83,20 +166,30 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (timeout >= 0)
|
||||
{
|
||||
struct pollfd pollfd = { childPipeFd, POLLIN, 0 };
|
||||
if (poll(&pollfd, 1, timeout) == 0)
|
||||
int pollret = poll(&pollfd, 1, timeout);
|
||||
if (pollret == 0)
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
else if (pollret < 0)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
if (errno == EINTR)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
// 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
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error";
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
@@ -276,8 +369,10 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
psinfo_t proc;
|
||||
if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc))
|
||||
{
|
||||
ffStrbufSetS(exe, proc.pr_psargs);
|
||||
ffStrbufSubstrBeforeFirstC(exe, ' ');
|
||||
const char* args = proc.pr_psargs;
|
||||
if (args[0] == '-') ++args;
|
||||
const char* end = strchr(args, ' ');
|
||||
ffStrbufSetNS(exe, end ? (uint32_t) (end - args) : (uint32_t) strlen(args), args);
|
||||
}
|
||||
|
||||
if (exePath)
|
||||
@@ -301,10 +396,30 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
if (proc)
|
||||
{
|
||||
char** argv = kvm_getargv(kd, proc, 0);
|
||||
if (argv) ffStrbufSetS(exe, argv[0]);
|
||||
if (argv)
|
||||
{
|
||||
const char* arg0 = argv[0];
|
||||
if (arg0[0] == '-') arg0++;
|
||||
ffStrbufSetS(exe, arg0);
|
||||
}
|
||||
}
|
||||
kvm_close(kd);
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
image_info info;
|
||||
int32 cookie = 0;
|
||||
|
||||
while (get_next_image_info(pid, &cookie, &info) == B_OK)
|
||||
{
|
||||
if (info.type != B_APP_IMAGE) continue;
|
||||
ffStrbufSetS(exe, info.name);
|
||||
|
||||
if (exePath)
|
||||
ffStrbufSet(exePath, exe);
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(exe->length == 0)
|
||||
@@ -471,6 +586,18 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
|
||||
if (!proc)
|
||||
return "kvm_getprocs() failed";
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
team_info info;
|
||||
if (get_team_info(pid, &info) == B_OK)
|
||||
{
|
||||
ffStrbufSetS(name, info.name);
|
||||
if (ppid)
|
||||
*ppid = info.parent;
|
||||
}
|
||||
|
||||
FF_UNUSED(tty);
|
||||
|
||||
#else
|
||||
|
||||
return "Unsupported platform";
|
||||
|
||||
@@ -81,7 +81,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
if (hChildPipeWrite == INVALID_HANDLE_VALUE)
|
||||
return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed";
|
||||
|
||||
PROCESS_INFORMATION piProcInfo = {0};
|
||||
PROCESS_INFORMATION piProcInfo = {};
|
||||
|
||||
BOOL success;
|
||||
|
||||
@@ -91,9 +91,15 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
if (useStdErr)
|
||||
{
|
||||
siStartInfo.hStdOutput = ffGetNullFD();
|
||||
siStartInfo.hStdError = hChildPipeWrite;
|
||||
}
|
||||
else
|
||||
{
|
||||
siStartInfo.hStdOutput = hChildPipeWrite;
|
||||
siStartInfo.hStdError = ffGetNullFD();
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate();
|
||||
argvToCmdline(argv, &cmdline);
|
||||
@@ -130,7 +136,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
#if __aarch64__
|
||||
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
|
||||
#else
|
||||
// To support Windows 7
|
||||
if (timeout >= 0 && WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
@@ -138,13 +148,18 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
||||
#endif
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
return NULL;
|
||||
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "GetOverlappedResult(hChildPipeRead) failed";
|
||||
return "GetOverlappedResult"
|
||||
#if __aarch64__
|
||||
"Ex"
|
||||
#endif
|
||||
"(hChildPipeRead) failed";
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -169,6 +184,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;
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ void ffTempsAppendNum(double celsius, FFstrbuf* buffer, FFColorRangeConfig confi
|
||||
|
||||
switch (options->tempUnit)
|
||||
{
|
||||
case FF_TEMPERATURE_UNIT_DEFAULT:
|
||||
case FF_TEMPERATURE_UNIT_CELSIUS:
|
||||
ffStrbufAppendF(buffer, "%.*f°C", options->tempNdigits, celsius);
|
||||
break;
|
||||
|
||||
+14
-6
@@ -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);
|
||||
@@ -57,8 +65,8 @@
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
|
||||
{
|
||||
ts.tv_sec += ts.tv_sec / 1000;
|
||||
ts.tv_nsec += (ts.tv_nsec % 1000) * 1000000;
|
||||
ts.tv_sec += timeout / 1000;
|
||||
ts.tv_nsec += (timeout % 1000) * 1000000;
|
||||
if (pthread_timedjoin_np(thread, NULL, &ts) != 0)
|
||||
{
|
||||
pthread_kill(thread, SIGTERM);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <synchapi.h>
|
||||
#include <profileapi.h>
|
||||
#include <sysinfoapi.h>
|
||||
#elif defined(__HAIKU__)
|
||||
#include <OS.h>
|
||||
#endif
|
||||
|
||||
static inline double ffTimeGetTick(void) //In msec
|
||||
@@ -17,6 +19,8 @@ static inline double ffTimeGetTick(void) //In msec
|
||||
LARGE_INTEGER start;
|
||||
QueryPerformanceCounter(&start);
|
||||
return (double) start.QuadPart * 1000 / (double) frequency.QuadPart;
|
||||
#elif defined(__HAIKU__)
|
||||
return (double) system_time() / 1000.;
|
||||
#else
|
||||
struct timespec timeNow;
|
||||
clock_gettime(CLOCK_MONOTONIC, &timeNow);
|
||||
@@ -30,6 +34,8 @@ static inline uint64_t ffTimeGetNow(void)
|
||||
uint64_t timeNow;
|
||||
GetSystemTimeAsFileTime((FILETIME*) &timeNow);
|
||||
return (timeNow - 116444736000000000ull) / 10000ull;
|
||||
#elif defined(__HAIKU__)
|
||||
return (uint64_t) real_time_clock_usecs() / 1000u;
|
||||
#else
|
||||
struct timespec timeNow;
|
||||
clock_gettime(CLOCK_REALTIME, &timeNow);
|
||||
@@ -76,6 +82,62 @@ static inline const char* ffTimeToShortStr(uint64_t msec)
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Not thread-safe
|
||||
static inline const char* ffTimeToTimeStr(uint64_t msec)
|
||||
{
|
||||
if (msec == 0) return "";
|
||||
time_t tsec = (time_t) (msec / 1000);
|
||||
|
||||
static char buf[32];
|
||||
strftime(buf, sizeof(buf), "%T", localtime(&tsec));
|
||||
sprintf(buf + __builtin_strlen("00:00:00"), ".%03u", (unsigned) (msec % 1000));
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
typedef struct FFTimeGetAgeResult
|
||||
{
|
||||
uint32_t years;
|
||||
uint32_t daysOfYear;
|
||||
double yearsFraction;
|
||||
} FFTimeGetAgeResult;
|
||||
|
||||
static inline FFTimeGetAgeResult ffTimeGetAge(uint64_t birthMs, uint64_t nowMs)
|
||||
{
|
||||
FFTimeGetAgeResult result = {};
|
||||
if (__builtin_expect(birthMs == 0 || nowMs < birthMs, 0))
|
||||
return result;
|
||||
|
||||
time_t birth_s = (time_t) (birthMs / 1000);
|
||||
struct tm birth_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&birth_tm, &birth_s);
|
||||
#else
|
||||
localtime_r(&birth_s, &birth_tm);
|
||||
#endif
|
||||
|
||||
time_t now_s = (time_t) (nowMs / 1000);
|
||||
struct tm now_tm;
|
||||
#ifdef _WIN32
|
||||
localtime_s(&now_tm, &now_s);
|
||||
#else
|
||||
localtime_r(&now_s, &now_tm);
|
||||
#endif
|
||||
|
||||
result.years = (uint32_t) (now_tm.tm_year - birth_tm.tm_year);
|
||||
if (now_tm.tm_yday < birth_tm.tm_yday)
|
||||
result.years--;
|
||||
|
||||
birth_tm.tm_year += (int) result.years;
|
||||
birth_s = mktime(&birth_tm);
|
||||
uint32_t diff_s = (uint32_t) (now_s - birth_s);
|
||||
result.daysOfYear = diff_s / (24 * 60 * 60);
|
||||
|
||||
birth_tm.tm_year += 1;
|
||||
result.yearsFraction = (double) diff_s / (double) (mktime(&birth_tm) - birth_s) + result.years;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+214
-179
File diff suppressed because it is too large
Load Diff
@@ -1,24 +0,0 @@
|
||||
Usage: fastfetch --color <color>
|
||||
|
||||
Shortcut of `fastfetch --color-keys <color> --color-title <color>`.
|
||||
If no color is set, the main color of the logo will be used.
|
||||
|
||||
Following information applies to all settings
|
||||
|
||||
<color> must be a color encoding as ANSI escape sequences. It is inserted between "ESC[" and "m".
|
||||
Infos about them can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Examples:
|
||||
35: sets the color to magenta
|
||||
38;5;38: sets the color to 38th color of ANSI 256 colors
|
||||
4;92: sets the color to bright green with underline
|
||||
5;104: blinking text on a blue background
|
||||
|
||||
ANSI named colors are also supported:
|
||||
magenta: equivalent to `35`
|
||||
underline_bright_green: equivalent to `4;92`
|
||||
|
||||
After v2.15.0, some special keys can be used:
|
||||
keys: use the color set by `--color-keys`
|
||||
title: use the color set by `--color-title`
|
||||
output: use the color set by `--color-output`
|
||||
separator: use the color set by `--color-separator`
|
||||
@@ -1,4 +0,0 @@
|
||||
Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci"
|
||||
If a value starts with a ?, it is optional. An optional boolean value defaults to true if not specified.
|
||||
More detailed help messages for each options can be printed with "-h <option_without_dash_prefix>"
|
||||
All options can be made permanent with command "fastfetch <options> --gen-config"
|
||||
@@ -1,53 +0,0 @@
|
||||
A format string is a string that contains placeholders for values.
|
||||
These placeholders begin with a '{', containing the index of the value, and end with a '}'.
|
||||
For example the format string "Values: {1} ({2})", with the values "First" and "My second val", will produce "Values: First (My second val)".
|
||||
The format string can contain placeholders in any order and have multiple occurrences.
|
||||
To include spaces when setting from the command line, surround the whole string with double quotes (").
|
||||
|
||||
In 2.14.0 or newer, the value indices can be meaningful named tags.
|
||||
For example: "--title-format '{user-name-colored}{at-symbol-colored}{host-name-colored}'" is equivalent to "--title-format '{6}{7}{8}'"
|
||||
See "fastfetch -h title-format" for all supported tags.
|
||||
|
||||
In 2.17.0 or newer, a truncation length can be specified using syntax '<arg>:<trunc-length>`
|
||||
For example: "--title-format '{user-name:5}'" will truncate user name into 5-length string.
|
||||
If '<trunc-length>' is negative, an ellipsis … will be appended at the end when the original string is truncated.
|
||||
Note: The string length is counted in raw bytes. Multi-byte unicode characters and ANSI escape codes are not taken into account.
|
||||
|
||||
In 2.23.0 or newer, `<` or `>` can be specified instead of `:` to set a left or right padding.
|
||||
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.
|
||||
|
||||
To make formatting easier, a double open curly brace ("{{") will be printed as a single open curly brace and not counted as the beginning of a placeholder.
|
||||
If a value index is misformatted or wants a non-existing value, it will be printed as is, with the curly braces around it.
|
||||
If the last placeholder isn't closed, it will be treated like it was at the end of the format string.
|
||||
|
||||
To only print something if a variable is set, use "{?<index>} ... {?}".
|
||||
For example, to only print a second value if it is set, use "{?2} Second value: {2}{?}".
|
||||
If a "{?}" is found without an opener, it is printed as is.
|
||||
|
||||
To only print something if a variable is not set, do the same as with if, just replace every '?' with a '/'.
|
||||
For example to print a fallback for a second value if it is not set, use "{?2}{2}{?}{/2}Second value fallback{/}".
|
||||
|
||||
To stop formatting at any point in the format string, use "{-}".
|
||||
|
||||
To print something with color, start a placeholder with a '#' and then the linux terminal color encoding.
|
||||
"\033[" at the start, and an 'm' at the end is automatically added, so don't do that.
|
||||
A "{#}" is equivalent to a "{#0}" and resets everything to normal.
|
||||
For example to print something pink and underline, use "{#4;35}...{#}". "{#underline_magenta}" is also supported. See `fastfetch -h color` for detail.
|
||||
Information about what the numbers mean can be found here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
|
||||
Which escape codes are supported and how they look is defined by your terminal.
|
||||
|
||||
If a format string evaluates to an empty value, the whole line in the output will be discarded.
|
||||
You can therefore use --host-format " " to disable host output.
|
||||
Note that --host-format "" would evaluate as not set, and therefore use the built-in host format
|
||||
|
||||
Format string is also the way to go to set a fixed value - just use one without placeholders.
|
||||
For example when running in headless mode, you could use "--display-format Preferred".
|
||||
@@ -98,7 +98,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
// https://github.com/AsahiLinux/linux/blob/b5c05cbffb0488c7618106926d522cc3b43d93d5/drivers/power/supply/macsmc_power.c#L410-L419
|
||||
int year = (manufactureDate[0] - '0') * 10 + (manufactureDate[1] - '0') + 2000 - 8;
|
||||
int month = (manufactureDate[2] - '0') * 10 + (manufactureDate[3] - '0');
|
||||
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '5');
|
||||
int day = (manufactureDate[4] - '0') * 10 + (manufactureDate[3] - '0');
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", year, month, day);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "fastfetch.h"
|
||||
#include "battery.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <private/device/power_managment.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* parseBattery(int dfd, const char* battId, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = openat(dfd, battId, O_RDWR);
|
||||
if (fd < 0) return "openat() failed";
|
||||
|
||||
acpi_battery_info basic = {};
|
||||
if (ioctl(fd, GET_BATTERY_INFO, &basic, sizeof(basic)) != 0)
|
||||
return "ioctl(GET_BATTERY_INFO) failed";
|
||||
acpi_extended_battery_info extended = {};
|
||||
if (ioctl(fd, GET_EXTENDED_BATTERY_INFO, &extended, sizeof(extended)) != 0)
|
||||
return "ioctl(GET_EXTENDED_BATTERY_INFO) failed";
|
||||
|
||||
if (extended.last_full_charge == (uint32)-1)
|
||||
return "Skipped";
|
||||
|
||||
FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results);
|
||||
ffStrbufInitS(&battery->modelName, extended.model_number);
|
||||
ffStrbufInitS(&battery->manufacturer, extended.oem_info);
|
||||
ffStrbufInit(&battery->manufactureDate);
|
||||
ffStrbufInitS(&battery->technology, extended.type); // extended.technology?
|
||||
ffStrbufInit(&battery->status);
|
||||
ffStrbufInitS(&battery->serial, extended.serial_number);
|
||||
battery->temperature = FF_BATTERY_TEMP_UNSET;
|
||||
battery->cycleCount = extended.cycles;
|
||||
battery->timeRemaining = -1;
|
||||
battery->capacity = (double) basic.capacity * 100. / (double) extended.last_full_charge;
|
||||
|
||||
if (basic.state & BATTERY_DISCHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Discharging, ");
|
||||
if (basic.state & BATTERY_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "Charging, ");
|
||||
if (basic.state & BATTERY_CRITICAL_STATE)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
if (basic.state & BATTERY_NOT_CHARGING)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected, ");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/dev/power/acpi_battery/");
|
||||
if (!dir) return "opendir(/dev/power/acpi_battery) failed";
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
parseBattery(dirfd(dir), entry->d_name, results);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFl
|
||||
|
||||
if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(&result->manufacturer);
|
||||
ffStrbufTrimRightSpace(&tmpBuffer);
|
||||
if (ffStrbufEqualS(&tmpBuffer, "Critical"))
|
||||
{
|
||||
if (result->status.length)
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
#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 | O_CLOEXEC);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) 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, ");
|
||||
battery->timeRemaining = (int32_t)((double)curr / dischargeRate * 3600);
|
||||
}
|
||||
if (critical)
|
||||
ffStrbufAppendS(&battery->status, "Critical, ");
|
||||
if (acConnected)
|
||||
ffStrbufAppendS(&battery->status, "AC Connected");
|
||||
ffStrbufTrimRight(&battery->status, ' ');
|
||||
ffStrbufTrimRight(&battery->status, ',');
|
||||
}
|
||||
|
||||
prop_object_iterator_release(iter);
|
||||
}
|
||||
prop_object_iterator_release(itKey);
|
||||
prop_object_release(root);
|
||||
|
||||
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 | O_CLOEXEC);
|
||||
|
||||
if (devfd < 0) return "open(dev/apm, O_RDONLY | O_CLOEXEC) 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;
|
||||
}
|
||||
@@ -8,40 +8,31 @@
|
||||
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <batclass.h>
|
||||
#include <devguid.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
if(*hdev)
|
||||
SetupDiDestroyDeviceInfoList(*hdev);
|
||||
}
|
||||
//https://learn.microsoft.com/en-us/windows-hardware/drivers/install/using-device-interfaces
|
||||
ULONG cchDeviceInterfaces = 0;
|
||||
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&cchDeviceInterfaces, (LPGUID)&GUID_DEVCLASS_BATTERY, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
return "CM_Get_Device_Interface_List_SizeW() failed";
|
||||
|
||||
static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
|
||||
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
|
||||
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if(hdev == INVALID_HANDLE_VALUE)
|
||||
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
|
||||
if (cchDeviceInterfaces <= 1)
|
||||
return NULL; // Not found
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
|
||||
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
|
||||
wchar_t* FF_AUTO_FREE mszDeviceInterfaces = (wchar_t*)malloc(cchDeviceInterfaces * sizeof(wchar_t));
|
||||
cr = CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVCLASS_BATTERY, NULL, mszDeviceInterfaces, cchDeviceInterfaces, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
return "CM_Get_Device_Interface_ListW() failed";
|
||||
|
||||
for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1)
|
||||
{
|
||||
DWORD cbRequired = 0;
|
||||
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
|
||||
if(!pdidd)
|
||||
break; //Out of memory
|
||||
|
||||
pdidd->cbSize = sizeof(*pdidd);
|
||||
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
|
||||
continue;
|
||||
|
||||
HANDLE FF_AUTO_CLOSE_FD hBattery =
|
||||
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
CreateFileW(pDeviceInterface, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(hBattery == INVALID_HANDLE_VALUE)
|
||||
continue;
|
||||
@@ -99,7 +90,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
bqi.InformationLevel = BatteryManufactureDate;
|
||||
BATTERY_MANUFACTURE_DATE date;
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
|
||||
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year < 1000 ? date.Year + 1900 : date.Year, date.Month, date.Day);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -131,7 +122,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
|
||||
{
|
||||
BATTERY_STATUS bs;
|
||||
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
|
||||
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY && bi.FullChargedCapacity != 0)
|
||||
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
|
||||
else
|
||||
battery->capacity = 0;
|
||||
@@ -271,6 +262,6 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
|
||||
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
return options->useSetupApi
|
||||
? detectWithSetupApi(options, results)
|
||||
? detectWithCmApi(options, results)
|
||||
: detectWithNtApi(options, results);
|
||||
}
|
||||
|
||||
@@ -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. Note /boot/efi exists on BIOS system*/, FF_PATHTYPE_DIRECTORY)
|
||||
? "UEFI" : "BIOS");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
const char *ffDetectBios(FFBiosResult *bios)
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
|
||||
|
||||
@@ -27,6 +27,15 @@ typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
|
||||
};
|
||||
};
|
||||
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION;
|
||||
#elif __OpenBSD__
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#elif __sun
|
||||
#include <libdevinfo.h>
|
||||
#include <sys/sunddi.h>
|
||||
#endif
|
||||
|
||||
typedef struct FFSmbiosBios
|
||||
@@ -54,6 +63,7 @@ typedef struct FFSmbiosBios
|
||||
static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18,
|
||||
"FFSmbiosBios: Wrong struct alignment");
|
||||
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
{
|
||||
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
|
||||
@@ -89,6 +99,20 @@ const char* ffDetectBios(FFBiosResult* bios)
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#elif __sun
|
||||
di_node_t rootNode = di_init("/", DINFOPROP);
|
||||
if (rootNode != DI_NODE_NIL)
|
||||
{
|
||||
char* efiVersion = NULL;
|
||||
if (di_prop_lookup_strings(DDI_DEV_T_ANY, rootNode, "efi-version", &efiVersion) > 0)
|
||||
ffStrbufSetStatic(&bios->type, "UEFI");
|
||||
else
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
}
|
||||
di_fini(rootNode);
|
||||
#elif __HAIKU__ || __OpenBSD__
|
||||
// Currently SMBIOS detection is supported in legancy BIOS only
|
||||
ffStrbufSetStatic(&bios->type, "BIOS");
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -11,4 +11,4 @@ typedef struct FFBluetoothResult
|
||||
bool connected;
|
||||
} FFBluetoothResult;
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */);
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
@property (nonatomic) uint8_t batteryPercentSingle;
|
||||
@end
|
||||
|
||||
const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
NSArray<IOBluetoothDevice*>* ioDevices = IOBluetoothDevice.pairedDevices;
|
||||
if(!ioDevices)
|
||||
@@ -18,6 +18,9 @@ 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);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#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,
|
||||
#if __FreeBSD__
|
||||
bt_devremote_name_gen(dev->devname, &dev->bdaddr)
|
||||
#else
|
||||
dev->devname
|
||||
#endif
|
||||
);
|
||||
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 NULL;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
extern "C" {
|
||||
#include "bluetooth.h"
|
||||
#include "common/io/io.h"
|
||||
}
|
||||
|
||||
#include <bluetooth/LocalDevice.h>
|
||||
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
using namespace Bluetooth;
|
||||
FF_SUPPRESS_IO();
|
||||
|
||||
LocalDevice* dev = LocalDevice::GetLocalDevice();
|
||||
if (!dev) return NULL;
|
||||
|
||||
BString devClass;
|
||||
dev->GetDeviceClass().DumpDeviceClass(devClass);
|
||||
|
||||
FFBluetoothResult* device = (FFBluetoothResult*) ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, dev->GetFriendlyName());
|
||||
ffStrbufInitS(&device->address, bdaddrUtils::ToString(dev->GetBluetoothAddress()).String());
|
||||
ffStrbufInitS(&device->type, devClass.String());
|
||||
device->battery = 0;
|
||||
device->connected = true;
|
||||
|
||||
// TODO: more devices?
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -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(FF_MAYBE_UNUSED 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,7 +7,7 @@
|
||||
|
||||
#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, "dlopen bthprops.cpl failed", "bthprops.cpl", 1)
|
||||
@@ -20,13 +20,14 @@ 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";
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ const char* ffBluetoothDetectBattery(FFlist* devices)
|
||||
on_scope_exit releaseCallResult([&] { pCallResult && pCallResult->Release(); });
|
||||
|
||||
IWbemClassObject* pResultObject = nullptr;
|
||||
if (FAILED(pCallResult->GetResultObject(WBEM_INFINITE, &pResultObject)))
|
||||
if (FAILED(pCallResult->GetResultObject((LONG) WBEM_INFINITE, &pResultObject)))
|
||||
continue;
|
||||
on_scope_exit releaseResultObject([&] { pResultObject && pResultObject->Release(); });
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
#import <IOBluetooth/IOBluetooth.h>
|
||||
|
||||
// For some reason the official declaration of IOBluetoothHostController don't include property `controllers`
|
||||
// For some reason the official declaration of IOBluetoothHostController doesn't include property `controllers`
|
||||
@interface IOBluetoothHostController()
|
||||
+ (id)controllers;
|
||||
@end
|
||||
|
||||
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
{
|
||||
NSArray<IOBluetoothHostController*>* ctrls = IOBluetoothHostController.controllers;
|
||||
if(!ctrls)
|
||||
|
||||
@@ -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,7 +145,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
#ifdef FF_HAVE_DBUS
|
||||
return detectBluetooth(devices);
|
||||
#else
|
||||
FF_UNUSED(devices)
|
||||
FF_UNUSED(devices)
|
||||
return "Fastfetch was compiled without DBus support";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
ffStrbufInitS(&device->name, blri.localInfo.name);
|
||||
|
||||
BLUETOOTH_ADDRESS_STRUCT addr = { .ullLong = blri.localInfo.address };
|
||||
ffStrbufInitF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ffStrbufInitF(&device->address, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
addr.rgBytes[5],
|
||||
addr.rgBytes[4],
|
||||
addr.rgBytes[3],
|
||||
@@ -97,6 +97,8 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */)
|
||||
device->enabled = true;
|
||||
device->connectable = ffBluetoothIsConnectable(hRadio);
|
||||
device->discoverable = ffBluetoothIsDiscoverable(hRadio);
|
||||
|
||||
CloseHandle(hRadio);
|
||||
} while (ffBluetoothFindNextRadio(hFind, &hRadio));
|
||||
|
||||
ffBluetoothFindRadioClose(hFind);
|
||||
|
||||
@@ -9,9 +9,19 @@ const char* ffDetectBoard(FFBoardResult* result)
|
||||
if (!service)
|
||||
return "No IOPlatformExpertDevice found";
|
||||
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
|
||||
ffStrbufSetS(&result->name, name);
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef boardId = IORegistryEntryCreateCFProperty(service, CFSTR("board-id"), kCFAllocatorDefault, kNilOptions);
|
||||
if (boardId)
|
||||
ffCfStrGetString(boardId, &result->name);
|
||||
else
|
||||
{
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
|
||||
ffStrbufSetS(&result->name, name);
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(service, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
|
||||
if (version)
|
||||
ffCfStrGetString(version, &result->version);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
|
||||
if (manufacturer)
|
||||
|
||||
@@ -10,6 +10,8 @@ const char* ffDetectBoard(FFBoardResult* board)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ typedef struct FFBootmgrResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf firmware;
|
||||
uint16_t order;
|
||||
bool secureBoot;
|
||||
} FFBootmgrResult;
|
||||
|
||||
|
||||
@@ -2,18 +2,30 @@
|
||||
#include "efi_helper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <sys/efiio.h>
|
||||
#ifdef __OpenBSD__
|
||||
#include <dev/efi/efiio.h>
|
||||
#else
|
||||
#include <sys/efiio.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
typedef uint16_t efi_char;
|
||||
#endif
|
||||
|
||||
#ifndef EFI_GLOBAL_VARIABLE
|
||||
#define EFI_GLOBAL_VARIABLE { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } }
|
||||
#endif
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR);
|
||||
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR | O_CLOEXEC);
|
||||
if (efifd < 0) return "open(/dev/efi) failed";
|
||||
|
||||
uint8_t buffer[2048];
|
||||
struct efi_var_ioc ioc = {
|
||||
.vendor = { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } },
|
||||
.vendor = EFI_GLOBAL_VARIABLE,
|
||||
.data = buffer,
|
||||
};
|
||||
|
||||
@@ -23,8 +35,10 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2)
|
||||
return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed";
|
||||
|
||||
result->order = *(uint16_t*)buffer;
|
||||
|
||||
unsigned char hex[5];
|
||||
snprintf((char*) hex, sizeof(hex), "%04X", *(uint16_t*)buffer);
|
||||
snprintf((char*) hex, sizeof(hex), "%04X", result->order);
|
||||
ioc.datasize = sizeof(buffer);
|
||||
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0' };
|
||||
ioc.namesize = sizeof("Boot####") * 2;
|
||||
|
||||
@@ -11,8 +11,10 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "BootCurrent-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6)
|
||||
return "Failed to read efivar: BootCurrent";
|
||||
|
||||
uint16_t value = *(uint16_t *)&buffer[4];
|
||||
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, value);
|
||||
|
||||
result->order = *(uint16_t *)&buffer[4];
|
||||
|
||||
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, result->order);
|
||||
|
||||
ssize_t size = ffReadFileData((const char*) buffer, sizeof(buffer), buffer);
|
||||
if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer))
|
||||
@@ -20,7 +22,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)&buffer[4], result);
|
||||
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) == 6)
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) >= 5)
|
||||
result->secureBoot = buffer[4] == 1;
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "bootmgr.h"
|
||||
#include "efi_helper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
const char* enablePrivilege(const wchar_t* privilege)
|
||||
{
|
||||
HANDLE token;
|
||||
FF_AUTO_CLOSE_FD HANDLE token = NULL;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||
return "OpenProcessToken() failed";
|
||||
|
||||
@@ -32,13 +33,12 @@ const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
if (enablePrivilege(L"SeSystemEnvironmentPrivilege") != NULL)
|
||||
return "Failed to enable SeSystemEnvironmentPrivilege";
|
||||
|
||||
uint16_t value;
|
||||
if (GetFirmwareEnvironmentVariableW(L"BootCurrent", L"{" FF_EFI_GLOBAL_GUID L"}", &value, sizeof(value)) != 2)
|
||||
if (GetFirmwareEnvironmentVariableW(L"BootCurrent", L"{" FF_EFI_GLOBAL_GUID L"}", &result->order, sizeof(result->order)) != 2)
|
||||
return "GetFirmwareEnvironmentVariableW(BootCurrent) failed";
|
||||
|
||||
uint8_t buffer[2048];
|
||||
wchar_t key[16];
|
||||
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", value);
|
||||
swprintf(key, ARRAY_SIZE(key), L"Boot%04X", result->order);
|
||||
uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer));
|
||||
if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer))
|
||||
return "GetFirmwareEnvironmentVariableW(Boot####) failed";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user