tools: Add hal-compatibility-checker 59/303659/8
authorYoungjae Cho <y0.cho@samsung.com>
Tue, 2 Jan 2024 11:14:35 +0000 (20:14 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Mon, 15 Jan 2024 09:04:08 +0000 (18:04 +0900)
Provide tool for executing compatibility checker of libhalcc by command.
See 'hal-compatibility-checker --help'.

Change-Id: I3bfd46496997471dcd41d790cc702cc57664a01b
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
CMakeLists.txt
packaging/hal-api-common.spec
tools/hal-compatibility-checker/CMakeLists.txt [new file with mode: 0644]
tools/hal-compatibility-checker/main.c [new file with mode: 0644]

index 6c1e84aa1d25fd3ef3765772c95935fa94e9da8a..7b0d070de5ea08e16e7ee99711d7c2907d03ced8 100644 (file)
@@ -66,3 +66,4 @@ ADD_SUBDIRECTORY(halcc)
 ADD_SUBDIRECTORY(tests)
 
 ADD_SUBDIRECTORY(tools/lshal)
+ADD_SUBDIRECTORY(tools/hal-compatibility-checker)
index e728d5fae5a6b697340b06cc4337c1337376333f..73f8e89561792ac0f2726cb0c2c0e017e0f9f70d 100644 (file)
@@ -107,6 +107,7 @@ systemd-tmpfiles /usr/lib/tmpfiles.d/hal-rpmdb-checker.conf --create
 %dir /hal
 %{_libdir}/hal/*.so*
 %{_bindir}/lshal
+%{_bindir}/hal-compatibility-checker
 %{_sysconfdir}/ld.so.conf.d/libhal-api.conf
 %{_systemdgeneratordir}/systemd-hal-firmware-generator
 
diff --git a/tools/hal-compatibility-checker/CMakeLists.txt b/tools/hal-compatibility-checker/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c3b6c13
--- /dev/null
@@ -0,0 +1,9 @@
+PROJECT(hal-compatibility-checker C)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/halcc/include)
+
+ADD_EXECUTABLE(${PROJECT_NAME} main.c)
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES INSTALL_RPATH ${LIBDIR}/hal)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE libhalcc)
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/)
diff --git a/tools/hal-compatibility-checker/main.c b/tools/hal-compatibility-checker/main.c
new file mode 100644 (file)
index 0000000..1bf188a
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2024 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 <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <hal-common.h>
+#include <halcc/hal-compatibility-checker.h>
+
+#define DEFAULT_PLATFORM_MANIFEST_DIR          "/etc/hal"
+#define DEFAULT_HAL_INFO_INI                           "/hal/etc/hal-info.ini"
+
+#define HCC_BUF_MAX            (256)
+#define BOLD(STR)      "\e[1m"STR"\e[m"
+
+enum {
+       OPT_START = 0,
+       OPT_HELP = OPT_START,
+       OPT_PLATFORM,
+       OPT_SKIP_IF_RESULT_EXIST,
+       OPT_REDIRECT_ALL,
+       OPT_REDIRECT_STDOUT,
+       OPT_REDIRECT_STDERR,
+       OPT_END,
+};
+
+static const struct option long_option[] = {
+       [OPT_HELP]
+           = { "help",                 no_argument,            NULL,   'h' },
+
+       [OPT_PLATFORM]
+           = { "platform",             required_argument,      NULL,   'p' },
+
+       [OPT_SKIP_IF_RESULT_EXIST]
+           = { "skip-if-result-exist", optional_argument,      NULL,   0 },
+
+       [OPT_REDIRECT_ALL]
+               = { "redirect-all",     required_argument,      NULL,   0 },
+
+       [OPT_REDIRECT_STDOUT]
+               = { "redirect-stdout",  required_argument,      NULL,   0 },
+
+       [OPT_REDIRECT_STDERR]
+               = { "redirect-stderr",  required_argument,      NULL,   0 },
+
+       { 0, },
+};
+
+static int get_tizen_hal_version(int *major, int *minor)
+{
+       FILE *fp = NULL;
+       char *line = NULL;
+       size_t len = 0;
+       int found = 0;
+       int ret;
+
+       assert(major);
+       assert(minor);
+
+       fp = fopen(DEFAULT_HAL_INFO_INI, "r");
+       if (!fp)
+               return -errno;
+
+       while (getline(&line, &len, fp) != EOF) {
+               if (fscanf(fp, "Model=Tizen%d.%d", major, minor) == 2) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       fclose(fp);
+       fp = NULL;
+       free(line);
+       line = NULL;
+
+       return found ? 0 : -EINVAL;
+}
+
+static const char* default_platform_manifest_dir(void)
+{
+       static char dirpath[HCC_BUF_MAX] = { 0 , };
+       int major;
+       int minor;
+       int ret;
+
+       ret = get_tizen_hal_version(&major, &minor);
+       if (ret != 0)
+               return NULL;
+
+       snprintf(dirpath, sizeof(dirpath), DEFAULT_PLATFORM_MANIFEST_DIR"/%d.%d", major, minor);
+
+       return dirpath;
+}
+
+// check result is exist, return true on exist.
+static bool result_exist(const char *dir)
+{
+       // check result exists based on the directory 'dir'.
+       return false;
+}
+
+static int redirect_output(const char *file, int stdfd)
+{
+       int fd = open(file, O_WRONLY | O_APPEND | O_CREAT, 0644);
+       int newfd;
+
+       if (fd == -1) {
+               printf("hal-compatibility-checker: Failed to redirect output: %m\n");
+               return -1;
+       }
+
+       newfd = dup2(fd, stdfd);
+       close(fd);
+
+       return newfd;
+}
+
+static void show_help(void)
+{
+       printf(
+               "hal-compatibility-checker - check compatibility between hal-api and hal-backend\n"
+               "\n"
+               BOLD("USAGE\n")
+               "\thal-compatibility-checker [OPTION]...\n"
+               "\n"
+               BOLD("OPTION\n")
+               "\t-h, --help\n"
+               "\t\tshow this help.\n"
+               "\n"
+               "\t-p, --platform=DIRECTORY\n"
+               "\t\tspecify directory that holds platform manifest xml\n"
+               "\t\twhen it is not specified, use default path: %s\n"
+               "\n"
+               "\t--skip-if-result-exist[=DIRECTORY]\n"
+               "\t\tskip compatibility check if there exists a result of compatibility.\n"
+               "\t\tif DIRECTORY is given, locate a result based on the given DIRECTORY.\n"
+               "\n"
+               "\t--redirect-all=FILE\n"
+               "\t\tredirect stdout/stderr to FILE.\n"
+               "\n"
+               "\t--redirect-stdout=FILE\n"
+               "\t\tredirect stdout to FILE.\n"
+               "\n"
+               "\t--redirect-stderr=FILE\n"
+               "\t\tredirect stderr to FILE.\n"
+               , default_platform_manifest_dir()
+         );
+}
+
+static void compatibility_cb(enum hal_module module,
+       halcc_compatibility_e is_compatible, void *user_data)
+{
+       // do something
+}
+
+int main(int argc, char *argv[])
+{
+       int opt;
+       int help = 0;
+       int index;
+       bool skip_if_result_exist = false;
+       const char *skip_if_result_exist_dir = NULL;
+       const char *platform_manifest_dir = NULL;
+       const char *outfile = NULL;
+       const char *errfile = NULL;
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "hp:", long_option, &index);
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'h':
+                       help = 1;
+                       break;
+               case 'p':
+                       platform_manifest_dir = optarg;
+                       break;
+               case 0: // long-only options
+               {
+                       switch (index) {
+                       case OPT_SKIP_IF_RESULT_EXIST:
+                               skip_if_result_exist = true;
+                               skip_if_result_exist_dir = optarg;
+                               break;
+                       case OPT_REDIRECT_ALL:
+                               outfile = optarg;
+                               errfile = optarg;
+                               break;
+                       case OPT_REDIRECT_STDOUT:
+                               outfile = optarg;
+                               break;
+                       case OPT_REDIRECT_STDERR:
+                               errfile = optarg;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
+
+       if (help) {
+               show_help();
+               return 0;
+       }
+
+       if (outfile)
+               redirect_output(outfile, STDOUT_FILENO);
+
+       if (errfile)
+               redirect_output(errfile, STDERR_FILENO);
+
+       if (skip_if_result_exist && result_exist(skip_if_result_exist_dir)) {
+               printf("hal-compatibility-checker: skip checking\n");
+               return 0;
+       }
+
+       if (!platform_manifest_dir)
+               platform_manifest_dir = default_platform_manifest_dir();
+
+       halcc_check_compatibility(platform_manifest_dir, compatibility_cb, NULL);
+
+       return 0;
+}