Add delta-verifier, a binary which will allow us to check delta-device compatibility... 20/283820/6
authorAntoni Adaszkiewicz <a.adaszkiewi@samsung.com>
Thu, 27 Oct 2022 14:51:16 +0000 (16:51 +0200)
committerAntoni Adaszkiewicz <a.adaszkiewi@samsung.com>
Mon, 28 Nov 2022 11:55:03 +0000 (12:55 +0100)
for update-manager and upgrade-trigger.sh (in upgrade-tools)

Change-Id: I4f58c3380d8875240794ef839f1d8caca4538c33

CMakeLists.txt
delta-verifier/CMakeLists.txt [new file with mode: 0644]
delta-verifier/delta-verifier.c [new file with mode: 0644]
delta-verifier/delta-verifier.h [new file with mode: 0644]
packaging/update-control.spec

index 934b817dc8051c9369811a57c945ea398ccc94ff..32b0b071797c4db17b4ca4e1a44116e9e5b00aec 100644 (file)
@@ -70,3 +70,4 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTAL
 
 ADD_SUBDIRECTORY(src/plugin)
 ADD_SUBDIRECTORY(update-manager)
+ADD_SUBDIRECTORY(delta-verifier)
diff --git a/delta-verifier/CMakeLists.txt b/delta-verifier/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1d60153
--- /dev/null
@@ -0,0 +1,22 @@
+ADD_DEFINITIONS("-DDEBUG")
+
+SET(SRCS
+               delta-verifier.c
+)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${PROJECT_NAME}_pkgs REQUIRED capi-system-info)
+
+FOREACH(flag ${${PROJECT_NAME}_pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I./include")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
+
+SET(EXECNAME "delta-verifier")
+ADD_EXECUTABLE(${EXECNAME} ${SRCS})
+
+TARGET_LINK_LIBRARIES(${EXECNAME} PRIVATE ${${PROJECT_NAME}_pkgs_LDFLAGS} "-g" "-pthread")
+INSTALL(TARGETS ${EXECNAME} DESTINATION bin)
diff --git a/delta-verifier/delta-verifier.c b/delta-verifier/delta-verifier.c
new file mode 100644 (file)
index 0000000..1fe459c
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+
+Copyright © 2022 Samsung Electronics Co., Ltd.. All rights reserved.
+
+Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute
+this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear
+in all copies of this software.
+
+IN NO EVENT SHALL SAMSUNG ELECTRONICS CO., LTD. BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF SAMSUNG ELECTRONICS CO., LTD. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SAMSUNG ELECTRONICS CO., LTD. SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND SAMSUNG ELECTRONICS CO., LTD. HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+*/
+
+
+
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <system_info.h>
+
+#include "delta-verifier.h"
+
+static void print_usage(const char* msg)
+{
+       if (msg)
+               printf("%s\n", msg);
+
+       printf("\n\tprint_usage: --update_info_path filepath\n"
+       "\t\tfilepath -> filepath to update_info.ini file extracted from delta\n");
+}
+
+static int get_update_info_path(int argc, char** argv, char** dest)
+{
+       *dest = NULL;
+       if (argc != 3) {
+               print_usage("Invalid parameter count");
+               return -1;
+       }
+       const struct option long_options[] = {
+               {"update_info_path", required_argument, NULL, 0},
+               {0}
+       };
+       while (1) {
+               int option = getopt_long(argc, argv, "", long_options, NULL);
+               if (option < 0)
+                       break;
+               switch (option) {
+               case 0:
+                       if (*dest != NULL) {
+                               print_usage("Parameters repeated");
+                               free(*dest);
+                               return -1;
+                       }
+                       *dest = strdup(optarg);
+                       if (*dest == NULL) {
+                               ERR_ERRNO("strdup()");
+                               return -1;
+                       }
+                       break;
+               default:
+                       print_usage("Invalid parameters");
+                       if (*dest)
+                               free(*dest);
+                       return -1;
+               }
+       }
+       if (*dest == NULL) {
+               print_usage("Wrong parameters");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int write_variable_data_with_format(FILE* write_file, const char* var_name, char* var_value)
+{
+       char tmp[MAX_STRING];
+       snprintf(tmp, MAX_STRING, "%s=%s\n", var_name, var_value);
+       if (fwrite(tmp, 1, strlen(tmp), write_file) != strlen(tmp)) {
+               ERR("fwrite() not successful");
+               return -1;
+       }
+       return 0;
+}
+
+static int write_info_from_api(FILE* write_file)
+{
+       const char* var_names[NO_OF_API_VARIABLES] = {
+               "model_name",
+               "manufacturer",
+               "device_type"
+       };
+
+       for (int i = 0; i < NO_OF_API_VARIABLES; i++) {
+               char* info;
+               char tmp_name[MAX_STRING];
+               snprintf(tmp_name , MAX_STRING, "%s/%s", API_SYSTRM_PREFIX, var_names[i]);
+               if (system_info_get_platform_string(tmp_name, &info) < 0) {
+                       ERR("system_info_get_platform_string() fail.");
+                       return -1;
+               }
+
+               if (write_variable_data_with_format(write_file, var_names[i], info)) {
+                       free(info);
+                       return -1;
+               }
+
+               free(info);
+       }
+       return 0;
+}
+
+static size_t get_file_size(FILE* file)
+{
+       fseek(file, 0, SEEK_END);
+       size_t size = ftell(file);
+       fseek(file, 0 , SEEK_SET);
+
+       return size;
+}
+
+static int write_info_from_file(FILE* read_file, FILE* write_file)
+{
+       const char* var_names[NO_OF_CONFIG_VARIABLES] = {
+               "RELEASE_NAME",
+               "ARCH",
+               "DATE"
+       };
+
+       char full_var_names[NO_OF_CONFIG_VARIABLES][MAX_STRING];
+       for (int i = 0; i < NO_OF_CONFIG_VARIABLES; i++) {
+               snprintf(full_var_names[i], MAX_STRING, "%s%s", TIZEN_BUILD_PREFIX, var_names[i]);
+       }
+
+       size_t read_size = get_file_size(read_file);
+       char* read_buf = (char*)malloc(read_size);
+       if (read_buf == NULL) {
+               ERR_ERRNO("malloc()");
+               return -1;
+       }
+
+       if (fread(read_buf, 1, read_size, read_file) != read_size) {
+               ERR("fread() not successful");
+               free(read_buf);
+               return -1;
+       }
+
+       const char* separators = " =\n\"";
+       char* read_word = strtok(read_buf, separators);
+       int loop_iter = 0;
+       int processed = 0;
+
+       while(read_word != NULL) {
+               if (processed == NO_OF_CONFIG_VARIABLES)
+                       break;
+
+               loop_iter++;
+               if (loop_iter % 2 == 1) {
+                       for (int i = 0; i < NO_OF_API_VARIABLES; i++) {
+                               if (strcmp(full_var_names[i], read_word) == 0)
+                               {
+                                       processed++;
+                                       loop_iter++;
+                                       read_word = strtok(NULL, separators);
+
+                                       char lowercase_name[MAX_STRING];
+                                       strcpy(lowercase_name, full_var_names[i]);
+                                       for (int j = 0; j < strlen(lowercase_name); j++)
+                                               lowercase_name[j] = tolower(lowercase_name[j]);
+
+                                       char to_write[MAX_STRING];
+                                       if (snprintf(to_write, MAX_STRING, "%s=%s\n", lowercase_name, read_word) < 0) {
+                                               ERR_ERRNO("snprintf()");
+                                               return -1;
+                                       }
+
+                                       if (fwrite(to_write, 1, strlen(to_write), write_file) != strlen(to_write)) {
+                                               free(read_buf);
+                                               return -1;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+               read_word = strtok(NULL, separators);
+       }
+
+       free(read_buf);
+       return 0;
+}
+
+int compare_info_files(FILE* update_info_file, FILE* device_info_file)
+{
+       size_t update_info_size, device_info_size;
+       update_info_size = get_file_size(update_info_file);
+       device_info_size = get_file_size(device_info_file);
+
+       if (device_info_size != update_info_size)
+               return 1;
+
+       int ret = 0;
+       char* device_read_buf = NULL;
+       char* update_read_buf = NULL;
+
+       update_read_buf = (char*)malloc(update_info_size + 1);
+       if (update_read_buf == NULL) {
+               ERR_ERRNO("malloc()");
+               ret = -1;
+               goto cleanup;
+       }
+
+       device_read_buf = (char*)malloc(device_info_size + 1);
+       if (device_read_buf == NULL) {
+               ERR_ERRNO("malloc()");
+               ret = -1;
+               goto cleanup;
+       }
+
+       if (fread(update_read_buf, 1, update_info_size, update_info_file) != update_info_size) {
+               ERR("fread() not successful");
+               ret = -1;
+               goto cleanup;
+       }
+       update_read_buf[update_info_size] = '\0';
+
+       if (fread(device_read_buf, 1, device_info_size, device_info_file) != device_info_size) {
+               ERR("fread() not successful");
+               ret = -1;
+               goto cleanup;
+       }
+       device_read_buf[device_info_size] = '\0';
+
+       if (strcmp(update_read_buf, device_read_buf) != 0) {
+               ret = 1;
+       }
+
+cleanup:
+       if (update_read_buf)
+               free(update_read_buf);
+       if (device_read_buf)
+               free(device_read_buf);
+       return ret;
+}
+
+int verify_delta_device_compatability(char* update_info_file_path)
+{
+       int ret = 0;
+       FILE* update_original = NULL, * tizen_build_conf = NULL, * device_info = NULL;
+
+       if ((update_original = fopen(update_info_file_path, "r")) == NULL) {
+               ERR_ERRNO("fopen()");
+               ret = -1;
+               goto cleanup;
+       }
+
+       if ((device_info = fopen(DEVICE_INFO_PATH, "r")) == NULL) {
+               if ((device_info = fopen(DEVICE_INFO_PATH, "w+")) == NULL) {
+                       ERR_ERRNO("fopen()");
+                       ret = -1;
+                       goto cleanup;
+               }
+
+               if ((tizen_build_conf = fopen(TIZEN_BUILD_CONFIG_PATH, "r")) == NULL) {
+                       ERR_ERRNO("fopen()");
+                       ret = -1;
+                       goto cleanup;
+               }
+
+               if (write_info_from_api(device_info) < 0) {
+                       ERR("write_info_from_api()");
+                       ret = -1;
+                       goto cleanup;
+               }
+
+               if (write_info_from_file(tizen_build_conf, device_info) < 0) {
+                       ERR("write_info_from_api()");
+                       ret = -1;
+                       goto cleanup;
+               }
+       }
+
+       int comparison_result;
+       if ((comparison_result = compare_info_files(update_original, device_info)) < 0) {
+               ERR("compare_info_file()");
+               ret = -1;
+               goto cleanup;
+       } else if (comparison_result == 0) {
+               // delete device info only if successful
+               fclose(device_info);
+               device_info = NULL;
+               unlink(DEVICE_INFO_PATH);
+               ret = 0;
+       } else {
+               ret = 1;
+       }
+
+cleanup:
+       if (update_original != NULL)
+               fclose(update_original);
+
+       if (tizen_build_conf != NULL)
+               fclose(tizen_build_conf);
+
+       if (device_info != NULL)
+               fclose(device_info);
+
+       return ret;
+}
+
+int main(int argc, char** argv)
+{
+       char* update_info_path;
+       if (get_update_info_path(argc, argv, &update_info_path) < 0) {
+               ERR("Parameter verification failed.");
+               return -1;
+       }
+
+       int ret = verify_delta_device_compatability(update_info_path);
+
+       free(update_info_path);
+
+       if (ret < 0)
+               ERR("Delta verification failed due to an unexpected error.");
+       else if (ret == 0)
+               printf("Delta is compatible with this device\n");
+       else
+               printf("Delta is not compatible with this device\n");
+
+       return ret;
+}
\ No newline at end of file
diff --git a/delta-verifier/delta-verifier.h b/delta-verifier/delta-verifier.h
new file mode 100644 (file)
index 0000000..a32222a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+
+Copyright © 2022 Samsung Electronics Co., Ltd.. All rights reserved.
+
+Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute
+this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear
+in all copies of this software.
+
+IN NO EVENT SHALL SAMSUNG ELECTRONICS CO., LTD. BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF SAMSUNG ELECTRONICS CO., LTD. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+SAMSUNG ELECTRONICS CO., LTD. SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND SAMSUNG ELECTRONICS CO., LTD. HAS NO OBLIGATION TO PROVIDE
+MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+*/
+
+
+
+#pragma once
+
+#ifdef DEBUG
+#define ERR_ERRNO(source) (perror(source),\
+            fprintf(stderr,"%s:%d\n",__FILE__,__LINE__))
+#define ERR(source) fprintf(stderr,"[%s:%d] %s\n",__FILE__,__LINE__, source)
+#else
+#define ERR_ERRNO(source) do {} while(0)
+#define ERR(source) do {} while(0)
+#endif
+
+#define TIZEN_BUILD_CONFIG_PATH "/etc/tizen-build.conf"
+#define TMP_DIR "/tmp/"
+#define DEVICE_INFO_PATH TMP_DIR "device-info.ini"
+
+#define API_TIZEN_PREFIX "http://tizen.org"
+#define API_SYSTRM_PREFIX API_TIZEN_PREFIX "/system"
+#define TIZEN_BUILD_PREFIX "TZ_BUILD_"
+
+#define NO_OF_API_VARIABLES 3
+#define NO_OF_CONFIG_VARIABLES 3
+#define MAX_STRING 100
\ No newline at end of file
index 8f6f9451ac24eb6575a1a1dcfa22c7727e3f423a..902d2782934684f990f0279fa05dc754fad27bf4 100644 (file)
@@ -95,6 +95,7 @@ ln -s ../%{service_file} %{buildroot}/%{_unitdir}/multi-user.target.wants/%{serv
 
 %files daemon
 %{_bindir}/update-manager
+%{_bindir}/delta-verifier
 %{dbus_conf_directory}/%{dbus_conf_file}
 %{_unitdir}/%{service_file}
 %{_unitdir}/multi-user.target.wants/%{service_file}