Support Process Name Setter/Getter 15/260615/18
authorHwankyu Jhun <h.jhun@samsung.com>
Tue, 29 Jun 2021 23:55:17 +0000 (08:55 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 2 Jul 2021 03:25:18 +0000 (12:25 +0900)
Some daemons want to commucate with the running applications using IPC API
of App Framework like rpc-port or message-port. To use APIs, the application ID
is required. Even if the process is not the Tizen application, we support to set
the name of the process.

Removes:
 - aul_proc_get_usr_bypid()

Adds:
 - aul_proc_get_uid()
 - aul_proc_get_attr()
 - aul_proc_get_cmdline()
 - aul_proc_register()
 - aul_proc_deregister()
 - aul_proc_get_name()
 - aul_proc_get_extra()

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/260615/
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/260623/

Change-Id: Id624ce33422626edb29edf2942b7cf5825d78f5f
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
aul/common/file_descriptor.hh [new file with mode: 0644]
include/aul_cmd.h
include/aul_key.h
include/aul_proc.h
src/aul_cmd.c
src/aul_proc.c [deleted file]
src/aul_proc.cc [new file with mode: 0644]
tool/aul_test/aul_test.c

diff --git a/aul/common/file_descriptor.hh b/aul/common/file_descriptor.hh
new file mode 100644 (file)
index 0000000..80f9fd5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUL_COMMON_FILE_DESCRIPTOR_HH_
+#define AUL_COMMON_FILE_DESCRIPTOR_HH_
+
+#include <unistd.h>
+#include <sys/types.h>
+
+namespace aul {
+
+class FileDescriptor {
+ public:
+  FileDescriptor(int fd = -1) : fd_(fd) {}
+
+  virtual ~FileDescriptor() {
+    if (fd_ > -1)
+      close(fd_);
+  }
+
+  void Set(int fd) {
+    fd_ = fd;
+  }
+
+  int Get() const {
+    return fd_;
+  }
+
+  void Close() {
+    if (fd_ > -1) {
+      close(fd_);
+      fd_ = -1;
+    }
+  }
+
+  bool IsClosed() {
+    return fd_ < 0 ? true : false;
+  }
+
+ private:
+  int fd_;
+};
+
+}  // namespace aul
+
+#endif  // AUL_COMMON_FILE_DESCRIPTOR_HH_
index 218a878..9ded442 100644 (file)
@@ -201,6 +201,11 @@ enum app_cmd {
        APP_GET_APP_CONTROL_DEFAULT_APP = 159,
        APP_LIFECYCLE_GET_STATE = 160,
 
+       PROC_REGISTER = 161,
+       PROC_DEREGISTER = 162,
+       PROC_GET_NAME = 163,
+       PROC_GET_EXTRA = 164,
+
        APP_CMD_MAX
 };
 
index cea1a98..b7f5ad0 100644 (file)
  * @since_tizen 6.5
  */
 #define AUL_K_MOUNT_ALLOWED_RES_DIR     "__AUL_MOUNT_ALLOWED_RES_DIR__"
+
+/**
+ * @brief Definition for AUL: The name of the process.
+ * @since_tizen 6.5
+ */
+#define AUL_K_PROC_NAME                 "__AUL_PROC_NAME__"
+
+/**
+ * @brief Definition for AUL: The extra data of the process.
+ * @since_tizen 6.5
+ */
+#define AUL_K_PROC_EXTRA                "__AUL_PROC_EXTRA__"
index 29d89b6..39e9751 100644 (file)
 /*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
  *
- * Licensed under the Apache License, Version 2.0 (the License);
+ * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
+ * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#pragma once
+#ifndef __AUL_PROC_H__
+#define __AUL_RPOC_H__
 
+#include <sys/types.h>
 #include <unistd.h>
-#include <ctype.h>
+
+#include <aul.h>
+#include <bundle.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/*
- * This API is only for Appfw internally.
+/**
+ * @brief Gets the user ID of the process from the proc filesystem.
+ * @since_tizen 6.5
+ * @param[in]   pid             The process ID
+ * @param[out]  uid             The user ID
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_get_uid(pid_t pid, uid_t *uid);
+
+/**
+ * @brief Gets the SMACK label of the process from the proc filesystem.
+ * @since_tizen 6.5
+ * @param[in]   pid             The process ID
+ * @param[in]   buf             The buffer
+ * @param[in]   buf_size        The size of the buffer
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_get_attr(pid_t pid, char *buf, size_t buf_size);
+
+/**
+ * @brief Gets the cmdline of the process from the proc filesystem.
+ * @since_tizen 6.5
+ * @param[in]   pid             The process ID
+ * @param[in]   buf             The buffer
+ * @param[in]   buf_size        The size of the buffer
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_get_cmdline(pid_t pid, char *buf, size_t buf_size);
+
+/**
+ * @brief Registers the process information,
+ * @details This function registers the process information to the application manager daemon.
+ *          After calling this function, the other process can get the process information
+ *          using aul_proc_get_name() or aul_proc_get_extra().
+ * @since_tizen 6.5
+ * @param[in]   name            The process name
+ * @param[in]   extra           The extra data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
  */
-uid_t aul_proc_get_usr_bypid(int pid);
+int aul_proc_register(const char *name, bundle *extra);
+
+/**
+ * @brief Deregister the process information.
+ * @since_tizen 6.5
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_deregister(void);
+
+/**
+ * @brief Gets the process name.
+ * @since_tizen 6.5
+ * @remarks The @a name MUST be released using free().
+ * @param[in]   pid             The process ID
+ * @param[out]  name            The process name
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_get_name(pid_t pid, char **name);
+
+/**
+ * @brief Gets the extra data of the process.
+ * @since_tizen 6.5
+ * @reamrks The @a extra MUST be released using bundle_free().
+ * @param[in]   pid             The process ID
+ * @param[out]  extra           The extra data
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_proc_get_extra(pid_t pid, bundle **extra);
 
 #ifdef __cplusplus
 }
 #endif
+
+#endif /* __AUL_PROC_H__ */
index 684b765..3c26ec4 100644 (file)
@@ -203,6 +203,11 @@ API const char *aul_cmd_convert_to_string(int cmd)
                "APP_GET_APP_CONTROL_DEFAULT_APP",
                "APP_LIFECYCLE_GET_STATE",
 
+               "PROC_REGISTER",
+               "PROC_DEREGISTER",
+               "PROC_GET_NAME",
+               "PROC_GET_EXTRA",
+
                "CUSTOM_COMMAND"
        };
 
diff --git a/src/aul_proc.c b/src/aul_proc.c
deleted file mode 100644 (file)
index 4d40e22..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "aul_api.h"
-#include "aul_proc.h"
-#include "aul_util.h"
-
-#define MAX_CMD_BUFSZ 1024
-
-API uid_t aul_proc_get_usr_bypid(int pid)
-{
-       char buf[MAX_CMD_BUFSZ];
-       int ret;
-       uid_t uid;
-       struct stat DirStat;
-
-       snprintf(buf, sizeof(buf), "/proc/%d", pid);
-       ret = stat(buf, &DirStat);
-       if (ret < 0)
-               uid = (uid_t)-1;
-       else
-               uid = DirStat.st_uid;
-
-       return uid;
-}
-
diff --git a/src/aul_proc.cc b/src/aul_proc.cc
new file mode 100644 (file)
index 0000000..0d5abb3
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2000 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bundle_internal.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <bundle_cpp.h>
+
+#include <string>
+#include <memory>
+#include <mutex>
+
+#include "app_request.h"
+#include "aul_api.h"
+#include "aul_util.h"
+#include "include/aul_proc.h"
+#include "include/aul_sock.h"
+
+#include "aul/common/file_descriptor.hh"
+
+using namespace aul;
+using namespace aul::internal;
+
+namespace {
+
+class ProcContext {
+ public:
+  ProcContext() {}
+  ~ProcContext() {}
+
+  void SetName(std::string name) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    name_ = std::move(name);
+  }
+
+  const std::string& GetName() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return name_;
+  }
+
+  void SetExtra(tizen_base::Bundle extra) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    extra_ = std::move(extra);
+  }
+
+  tizen_base::Bundle& GetExtra() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return extra_;
+  }
+
+  void SetFd(int fd) {
+    std::lock_guard<std::mutex> lock(mutex_);
+    fd_.Set(fd);
+  }
+
+  void Close() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    fd_.Close();
+  }
+
+  bool IsClosed() {
+    std::lock_guard<std::mutex> lock(mutex_);
+    return fd_.IsClosed();
+  }
+
+ private:
+  FileDescriptor fd_;
+  std::string name_;
+  tizen_base::Bundle extra_;
+  mutable std::mutex mutex_;
+};
+
+int ReadFromPath(const std::string& path, char* buf, size_t buf_size) {
+  int fd = open(path.c_str(), O_RDONLY);
+  if (fd < 0) {
+    _E("open() is failed. path(%s), errno(%d)", path.c_str(), errno);
+    return AUL_R_ERROR;
+  }
+
+  FileDescriptor fd_closer(fd);
+  ssize_t bytes = read(fd, buf, buf_size - 1);
+  if (bytes <= 0) {
+    _E("read() is failed. errno(%d)", errno);
+    return AUL_R_ERROR;
+  }
+
+  buf[bytes] = '\0';
+  return AUL_R_OK;
+}
+
+int SendAndReceive(int cmd, pid_t pid, uid_t uid, bundle** response) {
+  int fd = AppRequest(cmd, uid)
+      .SetPid(pid)
+      .SendSimply(AUL_SOCK_ASYNC);
+  if (fd < 0 || sysconf(_SC_OPEN_MAX)) {
+    _E("Failed to send request. error(%d)", fd);
+    return fd;
+  }
+
+  FileDescriptor fd_closer(fd);
+  app_pkt_t* pkt = nullptr;
+  int ret = aul_sock_recv_reply_pkt(fd, &pkt);
+  if (ret < 0) {
+    _E("Failed to receive reply packet. error(%d)", ret);
+    return AUL_R_ECOMM;
+  }
+
+  std::unique_ptr<app_pkt_t, decltype(std::free)*> pkt_auto(pkt, std::free);
+  if (!(pkt->opt & AUL_SOCK_BUNDLE)) {
+    _E("Invalid protocol");
+    return AUL_R_ECOMM;
+  }
+
+  if (pkt->cmd != APP_GET_INFO_OK) {
+    _E("Failed to get name by pid(%d)", pid);
+    return AUL_R_ERROR;
+  }
+
+  *response = bundle_decode(pkt->data, pkt->len);
+  if (*response == nullptr) {
+    _E("bundle_decode() is failed");
+    return AUL_R_ERROR;
+  }
+
+  return AUL_R_OK;
+}
+
+ProcContext context;
+
+}  // namespace
+
+extern "C" API int aul_proc_get_uid(pid_t pid, uid_t* uid) {
+  if (pid < 1 || uid == nullptr) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  std::string path = "/proc/" + std::to_string(pid);
+  struct stat stat_buf;
+  int ret = stat(path.c_str(), &stat_buf);
+  if (ret < 0) {
+    _E("stat() is failed. path(%s), errno(%d)", path.c_str(), errno);
+    return AUL_R_ERROR;
+  }
+
+  *uid = stat_buf.st_uid;
+  return AUL_R_OK;
+}
+
+extern "C" API int aul_proc_get_attr(pid_t pid, char* buf, size_t buf_size) {
+  if (pid < 1 || buf == nullptr || buf_size <= 0) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  std::string path = "/proc/" + std::to_string(pid) + "/attr/current";
+  return ReadFromPath(path, buf, buf_size);
+}
+
+extern "C" API int aul_proc_get_cmdline(pid_t pid, char* buf, size_t buf_size) {
+  if (pid < 1 || buf == nullptr || buf_size <= 0) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
+  return ReadFromPath(path, buf, buf_size);
+}
+
+extern "C" API int aul_proc_register(const char* name, bundle* extra) {
+  if (name == nullptr || name[0] == '\0') {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  if (!context.IsClosed()) {
+    _E("Already registered. Please call aul_proc_unset_name() first");
+    return AUL_R_ERROR;
+  }
+
+  tizen_base::Bundle b {{AUL_K_PROC_NAME, name}};
+  if (extra) {
+    tizen_base::Bundle extra_data(extra, false, false);
+    auto raw = extra_data.ToRaw();
+    b.Add(AUL_K_PROC_EXTRA, reinterpret_cast<const char*>(raw.first.get()));
+  }
+
+  int ret = AppRequest(PROC_REGISTER, getuid())
+      .With(b)
+      .SendSimply(AUL_SOCK_ASYNC);
+  if (ret < 0) {
+    _E("Failed to send request. name(%s), error(%d)", name, ret);
+    return ret;
+  }
+
+  context.SetFd(ret);
+  context.SetName(name);
+  if (extra)
+    context.SetExtra(tizen_base::Bundle(extra, true, true));
+
+  return AUL_R_OK;
+}
+
+extern "C" API int aul_proc_deregister(void) {
+  if (context.IsClosed()) {
+    _E("Invalid context");
+    return AUL_R_ERROR;
+  }
+
+  int ret = AppRequest(PROC_DEREGISTER, getuid())
+      .SendSimply(AUL_SOCK_NOREPLY);
+  if (ret < 0) {
+    _E("Failed to send request. error(%d)", ret);
+    return ret;
+  }
+
+  context.Close();
+  return AUL_R_OK;
+}
+
+extern "C" API int aul_proc_get_name(pid_t pid, char** name) {
+  if (pid < 1 || name == nullptr) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  if (pid == getpid() && !context.IsClosed() && !context.GetName().empty()) {
+    *name = strdup(context.GetName().c_str());
+    if (*name == nullptr) {
+      _E("strdup() is failed");
+      return AUL_R_ENOMEM;
+    }
+
+    return AUL_R_OK;
+  }
+
+  bundle* response;
+  int ret = SendAndReceive(PROC_GET_NAME, pid, getuid(), &response);
+  if (ret != AUL_R_OK)
+    return ret;
+
+  tizen_base::Bundle b(response, false, true);
+  std::string val = b.GetString(AUL_K_PROC_NAME);
+  if (val.empty()) {
+    _E("Failed to get name");
+    return AUL_R_ERROR;
+  }
+
+  *name = strdup(val.c_str());
+  if (*name == nullptr) {
+    _E("strdup() is failed");
+    return AUL_R_ENOMEM;
+  }
+
+  return AUL_R_OK;
+}
+
+extern "C" API int aul_proc_get_extra(pid_t pid, bundle** extra) {
+  if (pid < 1 || extra == nullptr) {
+    _E("Invalid parameter");
+    return AUL_R_EINVAL;
+  }
+
+  if (pid == getpid() && !context.IsClosed()) {
+    auto& extra_data = context.GetExtra();
+    *extra = bundle_dup(extra_data.GetHandle());
+    if (*extra == nullptr) {
+      _E("bundle_dup() is failed");
+      return AUL_R_ENOMEM;
+    }
+
+    return AUL_R_OK;
+  }
+
+  bundle* response;
+  int ret = SendAndReceive(PROC_GET_EXTRA, pid, getuid(), &response);
+  if (ret != AUL_R_OK)
+    return ret;
+
+  tizen_base::Bundle b(response, false, true);
+  std::string raw = b.GetString(AUL_K_PROC_EXTRA);
+  if (raw.empty()) {
+    _E("Failed to get extra");
+    return AUL_R_ERROR;
+  }
+
+  tizen_base::Bundle extra_data(raw);
+  *extra = extra_data.Detach();
+  return AUL_R_OK;
+}
index d077a15..93d4a1c 100644 (file)
@@ -26,6 +26,7 @@
 #include "aul.h"
 #include "aul/api/aul_app_lifecycle.h"
 #include "aul_svc.h"
+#include "aul_proc.h"
 #include "menu_db_util.h"
 
 #define MAX_LOCAL_BUFSZ 128
@@ -826,6 +827,74 @@ static int get_app_lifecycle_test(void)
        return ret;
 }
 
+static void __foreach_extra_cb(const char *key, const int type, const bundle_keyval_t *kb,
+               void *user_data)
+{
+       printf("key: %s, type:%d\n", key, type);
+}
+
+static int register_proc_test(void)
+{
+       char *name = NULL;
+       bundle *extra = NULL;
+       int ret;
+
+       if (gargc > 3)
+               extra = create_internal_bundle(3);
+
+       printf("[aul_proc_register] %s\n", gargv[2]);
+       ret = aul_proc_register(gargv[2], extra);
+       if (extra)
+               bundle_free(extra);
+       printf("result: %d\n", ret);
+       if (ret != AUL_R_OK)
+               return ret;
+
+       printf("[aul_proc_get_name] %d\n", getpid());
+       ret = aul_proc_get_name(getpid(), &name);
+       printf("result: %d, name: %s\n", ret, name);
+       free(name);
+
+       extra = NULL;
+       printf("[aul_proc_get_extra] %d\n", getpid());
+       ret = aul_proc_get_extra(getpid(), &extra);
+       printf("result:%d\n", ret);
+       if (extra) {
+               bundle_foreach(extra, __foreach_extra_cb, NULL);
+               bundle_free(extra);
+       }
+
+       return ret;
+}
+
+static int get_proc_name_test(void)
+{
+       char *name = NULL;
+       int ret;
+
+       printf("[aul_proc_get_name] %s\n", gargv[2]);
+       ret = aul_proc_get_name(atoi(gargv[2]), &name);
+       printf("result: %d, name: %s\n", ret, name);
+       free(name);
+       return ret;
+}
+
+static int get_proc_extra_test(void)
+{
+       bundle* extra = NULL;
+       int ret;
+
+       printf("[aul_proc_get_extra] %s\n", gargv[2]);
+       ret = aul_proc_get_extra(atoi(gargv[2]), &extra);
+       printf("result: %d\n", ret);
+       if (extra) {
+               bundle_foreach(extra, __foreach_extra_cb, NULL);
+               bundle_free(extra);
+       }
+
+       return ret;
+}
+
 static int test_regex()
 {
        char *token;
@@ -974,6 +1043,12 @@ static test_func_t test_func[] = {
                "[usage] get_default_appid <operation> <uri> <mime>"},
        {"get_app_lifecycle", get_app_lifecycle_test, "aul_app_lifecycle_get_state",
                "[usage] get_app_lifecycle <appid>"},
+       {"register_proc", register_proc_test, "aul_proc_register",
+               "[usage] register_proc <name> <key> <value> <key> <value> ..."},
+       {"get_proc_name", get_proc_name_test, "aul_proc_get_name",
+               "[usage] get_proc_name <pid>"},
+       {"get_proc_extra", get_proc_extra_test, "aul_proc_get_extra",
+               "[usage] get_proc_extra <pid>"},
 };
 
 int callfunc(char *testname)