| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-05-23 11:08:32 +02:00
										 |  |  |  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-15 13:11:21 +01:00
										 |  |  | #include <AK/ByteBuffer.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-29 10:12:40 +02:00
										 |  |  | #include <AK/JsonArray.h>
 | 
					
						
							|  |  |  | #include <AK/JsonObject.h>
 | 
					
						
							|  |  |  | #include <AK/JsonValue.h>
 | 
					
						
							| 
									
										
										
										
											2023-02-09 03:02:46 +01:00
										 |  |  | #include <LibCore/File.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 15:04:03 +01:00
										 |  |  | #include <LibCore/ProcessStatisticsReader.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | #include <pwd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | namespace Core { | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | HashMap<uid_t, DeprecatedString> ProcessStatisticsReader::s_usernames; | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-22 05:09:11 +01:00
										 |  |  | ErrorOr<AllProcessesStatistics> ProcessStatisticsReader::get_all(SeekableStream& proc_all_file, bool include_usernames) | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-01-22 05:09:11 +01:00
										 |  |  |     TRY(proc_all_file.seek(0, SeekMode::SetPosition)); | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-14 12:05:59 -06:00
										 |  |  |     AllProcessesStatistics all_processes_statistics; | 
					
						
							| 
									
										
										
										
											2019-07-10 15:32:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-11 17:49:00 +01:00
										 |  |  |     auto file_contents = TRY(proc_all_file.read_until_eof()); | 
					
						
							| 
									
										
										
										
											2022-12-08 14:50:31 +01:00
										 |  |  |     auto json_obj = TRY(JsonValue::from_string(file_contents)).as_object(); | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |     json_obj.get_array("processes"sv)->for_each([&](auto& value) { | 
					
						
							| 
									
										
										
										
											2019-06-29 10:12:40 +02:00
										 |  |  |         const JsonObject& process_object = value.as_object(); | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |         Core::ProcessStatistics process; | 
					
						
							| 
									
										
										
										
											2019-07-17 22:22:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // kernel data first
 | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |         process.pid = process_object.get_u32("pid"sv).value_or(0); | 
					
						
							|  |  |  |         process.pgid = process_object.get_u32("pgid"sv).value_or(0); | 
					
						
							|  |  |  |         process.pgp = process_object.get_u32("pgp"sv).value_or(0); | 
					
						
							|  |  |  |         process.sid = process_object.get_u32("sid"sv).value_or(0); | 
					
						
							|  |  |  |         process.uid = process_object.get_u32("uid"sv).value_or(0); | 
					
						
							|  |  |  |         process.gid = process_object.get_u32("gid"sv).value_or(0); | 
					
						
							|  |  |  |         process.ppid = process_object.get_u32("ppid"sv).value_or(0); | 
					
						
							|  |  |  |         process.kernel = process_object.get_bool("kernel"sv).value_or(false); | 
					
						
							|  |  |  |         process.name = process_object.get_deprecated_string("name"sv).value_or(""); | 
					
						
							|  |  |  |         process.executable = process_object.get_deprecated_string("executable"sv).value_or(""); | 
					
						
							|  |  |  |         process.tty = process_object.get_deprecated_string("tty"sv).value_or(""); | 
					
						
							|  |  |  |         process.pledge = process_object.get_deprecated_string("pledge"sv).value_or(""); | 
					
						
							|  |  |  |         process.veil = process_object.get_deprecated_string("veil"sv).value_or(""); | 
					
						
							| 
									
										
										
										
											2023-06-09 17:22:07 +01:00
										 |  |  |         process.creation_time = UnixDateTime::from_nanoseconds_since_epoch(process_object.get_i64("creation_time"sv).value_or(0)); | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |         process.amount_virtual = process_object.get_u32("amount_virtual"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_resident = process_object.get_u32("amount_resident"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_shared = process_object.get_u32("amount_shared"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_dirty_private = process_object.get_u32("amount_dirty_private"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_clean_inode = process_object.get_u32("amount_clean_inode"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_purgeable_volatile = process_object.get_u32("amount_purgeable_volatile"sv).value_or(0); | 
					
						
							|  |  |  |         process.amount_purgeable_nonvolatile = process_object.get_u32("amount_purgeable_nonvolatile"sv).value_or(0); | 
					
						
							| 
									
										
										
										
											2019-07-17 22:22:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |         auto& thread_array = process_object.get_array("threads"sv).value(); | 
					
						
							| 
									
										
										
										
											2019-12-30 14:50:40 +01:00
										 |  |  |         process.threads.ensure_capacity(thread_array.size()); | 
					
						
							| 
									
										
										
										
											2019-11-26 21:25:45 +01:00
										 |  |  |         thread_array.for_each([&](auto& value) { | 
					
						
							|  |  |  |             auto& thread_object = value.as_object(); | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  |             Core::ThreadStatistics thread; | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |             thread.tid = thread_object.get_u32("tid"sv).value_or(0); | 
					
						
							|  |  |  |             thread.times_scheduled = thread_object.get_u32("times_scheduled"sv).value_or(0); | 
					
						
							|  |  |  |             thread.name = thread_object.get_deprecated_string("name"sv).value_or(""); | 
					
						
							|  |  |  |             thread.state = thread_object.get_deprecated_string("state"sv).value_or(""); | 
					
						
							|  |  |  |             thread.time_user = thread_object.get_u64("time_user"sv).value_or(0); | 
					
						
							|  |  |  |             thread.time_kernel = thread_object.get_u64("time_kernel"sv).value_or(0); | 
					
						
							|  |  |  |             thread.cpu = thread_object.get_u32("cpu"sv).value_or(0); | 
					
						
							|  |  |  |             thread.priority = thread_object.get_u32("priority"sv).value_or(0); | 
					
						
							|  |  |  |             thread.syscall_count = thread_object.get_u32("syscall_count"sv).value_or(0); | 
					
						
							|  |  |  |             thread.inode_faults = thread_object.get_u32("inode_faults"sv).value_or(0); | 
					
						
							|  |  |  |             thread.zero_faults = thread_object.get_u32("zero_faults"sv).value_or(0); | 
					
						
							|  |  |  |             thread.cow_faults = thread_object.get_u32("cow_faults"sv).value_or(0); | 
					
						
							| 
									
										
										
										
											2023-06-10 19:29:48 +01:00
										 |  |  |             thread.unix_socket_read_bytes = thread_object.get_u64("unix_socket_read_bytes"sv).value_or(0); | 
					
						
							|  |  |  |             thread.unix_socket_write_bytes = thread_object.get_u64("unix_socket_write_bytes"sv).value_or(0); | 
					
						
							|  |  |  |             thread.ipv4_socket_read_bytes = thread_object.get_u64("ipv4_socket_read_bytes"sv).value_or(0); | 
					
						
							|  |  |  |             thread.ipv4_socket_write_bytes = thread_object.get_u64("ipv4_socket_write_bytes"sv).value_or(0); | 
					
						
							|  |  |  |             thread.file_read_bytes = thread_object.get_u64("file_read_bytes"sv).value_or(0); | 
					
						
							|  |  |  |             thread.file_write_bytes = thread_object.get_u64("file_write_bytes"sv).value_or(0); | 
					
						
							| 
									
										
										
										
											2019-11-26 21:25:45 +01:00
										 |  |  |             process.threads.append(move(thread)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 22:22:22 +02:00
										 |  |  |         // and synthetic data last
 | 
					
						
							| 
									
										
										
										
											2022-10-02 18:17:24 -06:00
										 |  |  |         if (include_usernames) { | 
					
						
							|  |  |  |             process.username = username_from_uid(process.uid); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-07-14 12:05:59 -06:00
										 |  |  |         all_processes_statistics.processes.append(move(process)); | 
					
						
							| 
									
										
										
										
											2019-06-29 10:12:40 +02:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-07-10 13:56:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 16:51:33 +00:00
										 |  |  |     all_processes_statistics.total_time_scheduled = json_obj.get_u64("total_time"sv).value_or(0); | 
					
						
							|  |  |  |     all_processes_statistics.total_time_scheduled_kernel = json_obj.get_u64("total_time_kernel"sv).value_or(0); | 
					
						
							| 
									
										
										
										
											2021-07-14 12:05:59 -06:00
										 |  |  |     return all_processes_statistics; | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 14:50:31 +01:00
										 |  |  | ErrorOr<AllProcessesStatistics> ProcessStatisticsReader::get_all(bool include_usernames) | 
					
						
							| 
									
										
										
										
											2021-01-03 10:08:51 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-02-09 03:02:46 +01:00
										 |  |  |     auto proc_all_file = TRY(Core::File::open("/sys/kernel/processes"sv, Core::File::OpenMode::Read)); | 
					
						
							| 
									
										
										
										
											2022-12-08 14:50:31 +01:00
										 |  |  |     return get_all(*proc_all_file, include_usernames); | 
					
						
							| 
									
										
										
										
											2021-01-03 10:08:51 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | DeprecatedString ProcessStatisticsReader::username_from_uid(uid_t uid) | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-07-10 13:56:28 +02:00
										 |  |  |     if (s_usernames.is_empty()) { | 
					
						
							|  |  |  |         setpwent(); | 
					
						
							|  |  |  |         while (auto* passwd = getpwent()) | 
					
						
							|  |  |  |             s_usernames.set(passwd->pw_uid, passwd->pw_name); | 
					
						
							|  |  |  |         endpwent(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto it = s_usernames.find(uid); | 
					
						
							|  |  |  |     if (it != s_usernames.end()) | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  |         return (*it).value; | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  |     return DeprecatedString::number(uid); | 
					
						
							| 
									
										
										
										
											2019-05-16 18:47:47 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | } |