Change preload and preload-rw package installation order 09/270109/4
authorJunghyun Yeon <jungh.yeon@samsung.com>
Wed, 26 Jan 2022 01:24:11 +0000 (10:24 +0900)
committerJunghyun Yeon <jungh.yeon@samsung.com>
Wed, 26 Jan 2022 02:08:04 +0000 (11:08 +0900)
Change installation order to install larger package prior than samller one.
install_preload_pkg tool deletes package file when its installation has done.
So if there are not enough space left in image,
installation will be failed due to lack of storage.
So change install larger package first to prevent this.

Change-Id: Ia1cc3ced1b0213f63f84eca8634016be3f889448
Signed-off-by: Junghyun Yeon <jungh.yeon@samsung.com>
src/install_preload_pkg/install_preload_pkg.c

index a72b8ec..f3669f9 100644 (file)
@@ -80,6 +80,24 @@ struct pkginfo {
        char *type;
 };
 
+typedef struct pkgfile_info {
+       char *path;
+       char *backend_type;
+       install_type install_type;
+       bool skip_check_reference;
+       uint pkg_size;
+} pkgfile_info;
+
+GList *pkgfile_info_list;
+
+static void __free_pkgfile_info_list(gpointer data)
+{
+       pkgfile_info *info = (pkgfile_info *)data;
+       free(info->path);
+       free(info->backend_type);
+       free(info);
+}
+
 static void __free_pkginfo(gpointer data)
 {
        struct pkginfo *info = (struct pkginfo *)data;
@@ -119,17 +137,18 @@ static void __make_preload_rw_list(GList *pkg_list)
        fclose(file);
 }
 
-static int _install_preload_pkg(const char *backend, const char *directory,
-               bool readonly, bool skip_check_reference)
-{
+static int _add_pkgfile_info(const char *backend, const char *directory,
+               install_type type, bool skip_check_reference) {
        DIR *dir;
        struct dirent *file_info;
-       int ret;
-       char file_path[BUFSZE];
        char err_buf[BUFSZE];
-       GList *preload_rw_pkg_list = NULL;
-       package_manager_pkg_detail_info_t *pkg_info;
-       struct pkginfo *info;
+       char file_path[BUFSZE];
+       pkgfile_info *pkgfile;
+       int ret = 0;
+       FILE *fp;
+
+       if (directory == NULL || type == INSTALL_TYPE_UNDEFINED)
+               return -1;
 
        dir = opendir(directory);
        if (!dir) {
@@ -143,27 +162,106 @@ static int _install_preload_pkg(const char *backend, const char *directory,
                }
        }
 
-       _D("Loading pkg files from %s", directory);
-
        while ((file_info = readdir(dir)) != NULL) {
                if (file_info->d_name[0] == '.')
                        continue;
 
+               pkgfile = calloc(1, sizeof(pkgfile_info));
+               if (pkgfile == NULL) {
+                       _E("Out of memory\n");
+                       ret = -1;
+                       break;
+               }
+
                snprintf(file_path, sizeof(file_path), "%s/%s", directory,
                        file_info->d_name);
                _D("pkg file %s", file_path);
 
+               pkgfile->path = strdup(file_path);
+               if (pkgfile->path == NULL) {
+                       _E("Out of memory\n");
+                       __free_pkgfile_info_list((gpointer)pkgfile);
+                       closedir(dir);
+                       return -1;
+               }
+
+               pkgfile->backend_type = strdup(backend);
+               if (pkgfile->backend_type == NULL) {
+                       _E("Out of memory\n");
+                       __free_pkgfile_info_list((gpointer)pkgfile);
+                       closedir(dir);
+                       return -1;
+               }
+
+               pkgfile->install_type = type;
+               pkgfile->skip_check_reference = skip_check_reference;
+
+               fp = fopen(file_path, "r");
+               if (fp == NULL) {
+                       _E("Failed to open file:%s, errno:%d ", file_path, errno);
+                       __free_pkgfile_info_list((gpointer)pkgfile);
+                       closedir(dir);
+                       return -1;
+               }
+               fseek(fp, 0, SEEK_END);
+               pkgfile->pkg_size = ftell(fp);
+               fclose(fp);
+
+               pkgfile_info_list = g_list_prepend(pkgfile_info_list, pkgfile);
+       }
+
+       closedir(dir);
+
+       return ret;
+}
+
+static gint __pkgfileinfo_compare(gconstpointer a, gconstpointer b)
+{
+       pkgfile_info *a_info = (pkgfile_info *)a;
+       pkgfile_info *b_info = (pkgfile_info *)b;
+
+       // Larget package comes first
+       if (a_info->pkg_size < b_info->pkg_size)
+               return 1;
+       else if (a_info->pkg_size > b_info->pkg_size)
+               return -1;
+       else
+               return 0;
+}
+
+static void _sort_pkgfile_info_list() {
+       pkgfile_info_list = g_list_sort(pkgfile_info_list, __pkgfileinfo_compare);
+}
+
+static int _install_pkg_with_pkginfo()
+{
+       GList *tmp_list;
+       GList *preload_rw_pkg_list = NULL;
+       pkgfile_info *file_info;
+       struct pkginfo *preload_rw_pkginfo;
+       package_manager_pkg_detail_info_t *pkg_info;
+       int ret;
+       char err_buf[BUFSZE];
+
+       for (tmp_list = pkgfile_info_list; tmp_list != NULL;
+                       tmp_list = g_list_next(tmp_list)) {
+               file_info = (pkgfile_info *)tmp_list->data;
+               if (file_info == NULL || file_info->backend_type == NULL ||
+                               file_info->install_type == INSTALL_TYPE_UNDEFINED ||
+                               file_info->path == NULL)
+                       continue;
+
                pid_t pid = fork();
                if (pid == 0) {
-                       execl(backend, backend, "-i", file_path,
-                               readonly ? "--preload" : "--preload-rw",
-                               skip_check_reference ?
-                                       "--skip-check-reference" :
-                                       "",
+                       execl(file_info->backend_type, file_info->backend_type, "-i",
+                                       file_info->path,
+                                       (file_info->install_type == INSTALL_TYPE_PRELOAD) ?
+                                                       "--preload" : "--preload-rw",
+                                       file_info->skip_check_reference ?
+                                                       "--skip-check-reference" : "",
                                (char *)NULL);
                } else if (pid < 0) {
-                       _E("failed to fork and execute %s!", backend);
-                       closedir(dir);
+                       _E("failed to fork and execute %s!", file_info->backend_type);
                        g_list_free_full(preload_rw_pkg_list, __free_pkginfo);
                        return -1;
                }
@@ -172,70 +270,76 @@ static int _install_preload_pkg(const char *backend, const char *directory,
                        int status = 0;
                        waitpid(pid, &status, 0);
                        if (WIFEXITED(status) == 0 || WEXITSTATUS(status) != 0) {
-                               _E("Execution failed : %s", backend);
-                               closedir(dir);
+                               _E("Execution failed : %s", file_info->backend_type);
                                g_list_free_full(preload_rw_pkg_list, __free_pkginfo);
                                return -1;
                        }
                }
 
-               if (!readonly) {
-                       // make the preload-rw list
-                       pkg_info = pkgmgr_client_check_pkginfo_from_file(file_path);
-                       if (pkg_info == NULL) {
-                               _E("can not get pkg_info from [%s]\n", file_path);
-                               continue;
+               if (file_info->install_type == INSTALL_TYPE_PRELOAD) {
+                       ret = remove(file_info->path);
+                       if (ret < 0) {
+                               _E("Failed to remove [%s]: [%s]", file_info->path,
+                                               strerror_r(errno, err_buf,
+                                                               sizeof(err_buf)));
+                               g_list_free_full(preload_rw_pkg_list, __free_pkginfo);
+                               return -1;
                        }
+                       continue;
+               }
 
-                       info = calloc(1, sizeof(struct pkginfo));
-                       if (info == NULL) {
-                               _E("out of memory");
-                               pkgmgr_client_free_pkginfo(pkg_info);
-                               continue;
-                       }
-                       info->pkgid = strdup(pkg_info->pkgid);
-                       if (info->pkgid == NULL) {
-                               _E("out of memory");
-                               __free_pkginfo((struct pkginfo *)info);
-                               pkgmgr_client_free_pkginfo(pkg_info);
-                               continue;
-                       }
-                       info->version = strdup(pkg_info->version);
-                       if (info->version == NULL) {
-                               _E("out of memory");
-                               __free_pkginfo((struct pkginfo *)info);
-                               pkgmgr_client_free_pkginfo(pkg_info);
-                               continue;
-                       }
-                       info->type = strdup(pkg_info->pkg_type);
-                       if (info->type == NULL) {
-                               _E("out of memory");
-                               __free_pkginfo((struct pkginfo *)info);
-                               pkgmgr_client_free_pkginfo(pkg_info);
-                               continue;
-                       }
-                       preload_rw_pkg_list = g_list_append(preload_rw_pkg_list,
-                                       info);
+               // make the preload-rw list
+               pkg_info = pkgmgr_client_check_pkginfo_from_file(file_info->path);
+               if (pkg_info == NULL) {
+                       _E("can not get pkg_info from [%s]\n", file_info->path);
+                       continue;
+               }
+
+               preload_rw_pkginfo = calloc(1, sizeof(struct pkginfo));
+               if (preload_rw_pkginfo == NULL) {
+                       _E("out of memory");
                        pkgmgr_client_free_pkginfo(pkg_info);
-                       pkg_info = NULL;
+                       continue;
+               }
+               preload_rw_pkginfo->pkgid = strdup(pkg_info->pkgid);
+               if (preload_rw_pkginfo->pkgid == NULL) {
+                       _E("out of memory");
+                       __free_pkginfo((struct pkginfo *)preload_rw_pkginfo);
+                       pkgmgr_client_free_pkginfo(pkg_info);
+                       continue;
                }
+               preload_rw_pkginfo->version = strdup(pkg_info->version);
+               if (preload_rw_pkginfo->version == NULL) {
+                       _E("out of memory");
+                       __free_pkginfo((struct pkginfo *)preload_rw_pkginfo);
+                       pkgmgr_client_free_pkginfo(pkg_info);
+                       continue;
+               }
+               preload_rw_pkginfo->type = strdup(pkg_info->pkg_type);
+               if (preload_rw_pkginfo->type == NULL) {
+                       _E("out of memory");
+                       __free_pkginfo((struct pkginfo *)preload_rw_pkginfo);
+                       pkgmgr_client_free_pkginfo(pkg_info);
+                       continue;
+               }
+               preload_rw_pkg_list = g_list_append(preload_rw_pkg_list,
+                               preload_rw_pkginfo);
+               pkgmgr_client_free_pkginfo(pkg_info);
+               pkg_info = NULL;
 
-               /* remove a file after installation */
-               ret = remove(file_path);
+               ret = remove(file_info->path);
                if (ret < 0) {
-                       _E("Failed to remove [%s]: [%s]", file_path,
+                       _E("Failed to remove [%s]: [%s]", file_info->path,
                                        strerror_r(errno, err_buf,
                                                        sizeof(err_buf)));
-                       closedir(dir);
                        g_list_free_full(preload_rw_pkg_list, __free_pkginfo);
                        return -1;
                }
        }
 
-       closedir(dir);
-
        __make_preload_rw_list(preload_rw_pkg_list);
        g_list_free_full(preload_rw_pkg_list, __free_pkginfo);
+
        return 0;
 }
 
@@ -318,20 +422,25 @@ int main(int argc, char *argv[])
        }
 
        if (is_default) {
-               if (_install_preload_pkg(TPK_BACKEND_CMD, TPK_DIR, true,
-                                       skip_check_reference) < 0)
+               if (_add_pkgfile_info(TPK_BACKEND_CMD, TPK_DIR,
+                               INSTALL_TYPE_PRELOAD, skip_check_reference) != 0)
                        goto error;
 
-               if (_install_preload_pkg(WGT_BACKEND_CMD, WGT_DIR, true,
-                                       skip_check_reference) < 0)
+               if (_add_pkgfile_info(TPK_BACKEND_CMD, TPK_RW_DIR,
+                               INSTALL_TYPE_PRELOAD_RW, skip_check_reference) != 0)
                        goto error;
 
-               if (_install_preload_pkg(TPK_BACKEND_CMD, TPK_RW_DIR, false,
-                                       skip_check_reference) < 0)
+               if (_add_pkgfile_info(WGT_BACKEND_CMD, WGT_DIR,
+                               INSTALL_TYPE_PRELOAD, skip_check_reference) != 0)
                        goto error;
 
-               if (_install_preload_pkg(WGT_BACKEND_CMD, WGT_RW_DIR, false,
-                                       skip_check_reference) < 0)
+               if (_add_pkgfile_info(WGT_BACKEND_CMD, WGT_RW_DIR,
+                               INSTALL_TYPE_PRELOAD_RW, skip_check_reference) != 0)
+                       goto error;
+
+               _sort_pkgfile_info_list();
+
+               if (_install_pkg_with_pkginfo() != 0)
                        goto error;
 
                return 0;
@@ -349,12 +458,19 @@ int main(int argc, char *argv[])
        else
                backend_cmd = WGT_BACKEND_CMD;
 
-       if (_install_preload_pkg(backend_cmd, pkg_path,
-                       (op_type == INSTALL_TYPE_PRELOAD) ? true : false,
-                       skip_check_reference) < 0)
+       if (_add_pkgfile_info(backend_cmd, pkg_path,
+                       op_type, skip_check_reference) != 0)
+               goto error;
+
+       _sort_pkgfile_info_list();
+
+       if (!_install_pkg_with_pkginfo() != 0)
                goto error;
 
 error:
+
+       g_list_free_full(pkgfile_info_list, __free_pkgfile_info_list);
+
        handle = open("/tmp/.preload_install_error",
                O_WRONLY | O_CREAT | O_APPEND | O_TRUNC, 0644);
        if (handle == -1) {