2 * Copyright (c) 2000 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "aul/include/aul_proc.h"
19 #include <bundle_cpp.h>
20 #include <bundle_internal.h>
22 #include <glib-unix.h>
27 #include <sys/types.h>
34 #include "aul/app_request.h"
35 #include "aul/aul_api.h"
36 #include "aul/aul_util.h"
37 #include "aul/common/file_descriptor.hh"
38 #include "aul/include/aul_sock.h"
41 using namespace aul::internal;
50 g_source_remove(source_);
53 void SetName(std::string name) {
54 std::lock_guard<std::mutex> lock(mutex_);
55 name_ = std::move(name);
58 const std::string& GetName() {
59 std::lock_guard<std::mutex> lock(mutex_);
63 void SetExtra(tizen_base::Bundle extra) {
64 std::lock_guard<std::mutex> lock(mutex_);
65 extra_ = std::move(extra);
68 tizen_base::Bundle& GetExtra() {
69 std::lock_guard<std::mutex> lock(mutex_);
74 std::lock_guard<std::mutex> lock(mutex_);
76 source_ = g_unix_fd_add(fd, G_IO_IN, UnixFdFunc, this);
80 std::lock_guard<std::mutex> lock(mutex_);
85 std::lock_guard<std::mutex> lock(mutex_);
86 return fd_.IsClosed();
91 std::lock_guard<std::mutex> lock(mutex_);
94 extra_ = tizen_base::Bundle();
98 static gboolean UnixFdFunc(gint fd, GIOCondition condition,
100 auto* proc_context = static_cast<ProcContext*>(user_data);
102 if (condition & G_IO_IN) {
103 int ret = aul_sock_recv_result_with_fd(fd);
105 _E("Failed to receive result. fd(%d)", fd);
106 proc_context->Reset();
107 return G_SOURCE_REMOVE;
109 _D("Result(%d) received", ret);
110 } else if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
111 _E("Socket was disconnected. fd(%d)", fd);
112 proc_context->Reset();
113 return G_SOURCE_REMOVE;
116 return G_SOURCE_CONTINUE;
122 tizen_base::Bundle extra_;
123 mutable std::mutex mutex_;
127 int ReadFromPath(const std::string& path, char* buf, size_t buf_size) {
128 int fd = open(path.c_str(), O_RDONLY);
130 _E("open() is failed. path(%s), errno(%d)", path.c_str(), errno);
134 FileDescriptor fd_closer(fd);
135 ssize_t bytes = read(fd, buf, buf_size - 1);
137 _E("read() is failed. errno(%d)", errno);
145 int SendAndReceive(int cmd, pid_t pid, uid_t uid, bundle** response) {
146 int fd = AppRequest(cmd, uid)
148 .SendSimply(AUL_SOCK_ASYNC);
149 if (fd < 0 || fd >= sysconf(_SC_OPEN_MAX)) {
150 _E("Failed to send request. error(%d)", fd);
154 FileDescriptor fd_closer(fd);
155 app_pkt_t* pkt = nullptr;
156 int ret = aul_sock_recv_reply_pkt(fd, &pkt);
158 _E("Failed to receive reply packet. error(%d)", ret);
162 std::unique_ptr<app_pkt_t, decltype(std::free)*> pkt_auto(pkt, std::free);
163 if (!(pkt->opt & AUL_SOCK_BUNDLE)) {
164 _E("Invalid protocol");
168 if (pkt->cmd != APP_GET_INFO_OK) {
169 _E("Failed to get name by pid(%d)", pid);
173 *response = bundle_decode(pkt->data, pkt->len);
174 if (*response == nullptr) {
175 _E("bundle_decode() is failed");
186 extern "C" API int aul_proc_get_uid(pid_t pid, uid_t* uid) {
187 if (pid < 1 || uid == nullptr) {
188 _E("Invalid parameter");
192 std::string path = "/proc/" + std::to_string(pid);
193 struct stat stat_buf;
194 int ret = stat(path.c_str(), &stat_buf);
196 _E("stat() is failed. path(%s), errno(%d)", path.c_str(), errno);
200 *uid = stat_buf.st_uid;
204 extern "C" API int aul_proc_get_attr(pid_t pid, char* buf, size_t buf_size) {
205 if (pid < 1 || buf == nullptr || buf_size <= 0) {
206 _E("Invalid parameter");
210 std::string path = "/proc/" + std::to_string(pid) + "/attr/current";
211 return ReadFromPath(path, buf, buf_size);
214 extern "C" API int aul_proc_get_cmdline(pid_t pid, char* buf, size_t buf_size) {
215 if (pid < 1 || buf == nullptr || buf_size <= 0) {
216 _E("Invalid parameter");
220 std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
221 return ReadFromPath(path, buf, buf_size);
224 extern "C" API int aul_proc_register(const char* name, bundle* extra) {
225 if (name == nullptr || name[0] == '\0') {
226 _E("Invalid parameter");
230 if (!context.IsClosed()) {
231 _E("Already registered. Please call aul_proc_deregister() first");
235 tizen_base::Bundle b {{AUL_K_PROC_NAME, name}};
237 tizen_base::Bundle extra_data(extra, false, false);
238 auto raw = extra_data.ToRaw();
239 b.Add(AUL_K_PROC_EXTRA, reinterpret_cast<const char*>(raw.first.get()));
242 int ret = AppRequest(PROC_REGISTER, getuid())
244 .SendSimply(AUL_SOCK_ASYNC);
246 _E("Failed to send request. name(%s), error(%d)", name, ret);
251 context.SetName(name);
253 context.SetExtra(tizen_base::Bundle(extra, true, true));
258 extern "C" API int aul_proc_deregister(void) {
259 if (context.IsClosed()) {
260 _E("Invalid context");
264 int ret = AppRequest(PROC_DEREGISTER, getuid())
265 .SendSimply(AUL_SOCK_NOREPLY);
267 _E("Failed to send request. error(%d)", ret);
275 extern "C" API int aul_proc_get_name(pid_t pid, char** name) {
276 if (pid < 1 || name == nullptr) {
277 _E("Invalid parameter");
281 if (pid == getpid() && !context.IsClosed() && !context.GetName().empty()) {
282 *name = strdup(context.GetName().c_str());
283 if (*name == nullptr) {
284 _E("strdup() is failed");
292 int ret = SendAndReceive(PROC_GET_NAME, pid, getuid(), &response);
296 tizen_base::Bundle b(response, false, true);
297 std::string val = b.GetString(AUL_K_PROC_NAME);
299 _E("Failed to get name");
303 *name = strdup(val.c_str());
304 if (*name == nullptr) {
305 _E("strdup() is failed");
312 extern "C" API int aul_proc_get_extra(pid_t pid, bundle** extra) {
313 if (pid < 1 || extra == nullptr) {
314 _E("Invalid parameter");
318 if (pid == getpid() && !context.IsClosed()) {
319 auto& extra_data = context.GetExtra();
320 *extra = bundle_dup(extra_data.GetHandle());
321 if (*extra == nullptr) {
322 _E("bundle_dup() is failed");
330 int ret = SendAndReceive(PROC_GET_EXTRA, pid, getuid(), &response);
334 tizen_base::Bundle b(response, false, true);
335 std::string raw = b.GetString(AUL_K_PROC_EXTRA);
337 _E("Failed to get extra");
341 tizen_base::Bundle extra_data(raw);
342 *extra = extra_data.Detach();