Change column name defined in query
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_pkginfo.c
index f2e8245..2b22e92 100644 (file)
@@ -32,9 +32,6 @@
 #include <libgen.h>
 #include <sys/stat.h>
 
-#include <libxml/parser.h>
-#include <libxml/xmlreader.h>
-#include <libxml/xmlschemas.h>
 #include <sqlite3.h>
 #include <glib.h>
 
@@ -48,7 +45,7 @@
 
 static bool _get_bool_value(const char *str)
 {
-       if (!strcmp(str, "true"))
+       if (str && !strcmp(str, "true"))
                return true;
        else
                return false;
@@ -56,8 +53,8 @@ static bool _get_bool_value(const char *str)
 
 static gint __compare_func(gconstpointer data1, gconstpointer data2)
 {
-       pkgmgrinfo_node_x *node1 = (pkgmgrinfo_node_x*)data1;
-       pkgmgrinfo_node_x *node2 = (pkgmgrinfo_node_x*)data2;
+       pkgmgrinfo_node_x *node1 = (pkgmgrinfo_node_x *)data1;
+       pkgmgrinfo_node_x *node2 = (pkgmgrinfo_node_x *)data2;
        if (node1->prop == node2->prop)
                return 0;
        else if (node1->prop > node2->prop)
@@ -69,7 +66,7 @@ static gint __compare_func(gconstpointer data1, gconstpointer data2)
 static void __destroy_each_node(gpointer data, gpointer user_data)
 {
        ret_if(data == NULL);
-       pkgmgrinfo_node_x *node = (pkgmgrinfo_node_x*)data;
+       pkgmgrinfo_node_x *node = (pkgmgrinfo_node_x *)data;
        if (node->value) {
                free(node->value);
                node->value = NULL;
@@ -85,7 +82,7 @@ static void __destroy_each_node(gpointer data, gpointer user_data)
 static void __cleanup_pkginfo(pkgmgr_pkginfo_x *data)
 {
        ret_if(data == NULL);
-       if (data->locale){
+       if (data->locale) {
                free((void *)data->locale);
                data->locale = NULL;
        }
@@ -96,37 +93,6 @@ static void __cleanup_pkginfo(pkgmgr_pkginfo_x *data)
        return;
 }
 
-static int __child_element(xmlTextReaderPtr reader, int depth)
-{
-       int ret = xmlTextReaderRead(reader);
-       int cur = xmlTextReaderDepth(reader);
-       while (ret == 1) {
-
-               switch (xmlTextReaderNodeType(reader)) {
-               case XML_READER_TYPE_ELEMENT:
-                       if (cur == depth + 1)
-                               return 1;
-                       break;
-               case XML_READER_TYPE_TEXT:
-                       /*text is handled by each function separately*/
-                       if (cur == depth + 1)
-                               return 0;
-                       break;
-               case XML_READER_TYPE_END_ELEMENT:
-                       if (cur == depth)
-                               return 0;
-                       break;
-               default:
-                       if (cur <= depth)
-                               return 0;
-                       break;
-               }
-               ret = xmlTextReaderRead(reader);
-               cur = xmlTextReaderDepth(reader);
-       }
-       return ret;
-}
-
 long long _pkgmgr_calculate_dir_size(char *dirname)
 {
        long long total = 0;
@@ -172,9 +138,8 @@ long long _pkgmgr_calculate_dir_size(char *dirname)
                                size occupied (in terms of 4096 blocks)*/
                        q = (fileinfo.st_size / BLOCK_SIZE);
                        r = (fileinfo.st_size % BLOCK_SIZE);
-                       if (r) {
+                       if (r)
                                q = q + 1;
-                       }
                        total += q * BLOCK_SIZE;
                        }
                }
@@ -184,189 +149,19 @@ long long _pkgmgr_calculate_dir_size(char *dirname)
 
 }
 
-static int _pkginfo_get_author(sqlite3 *db, const char *pkgid,
-               GList **author)
-{
-       static const char query_raw[] =
-               "SELECT author_name, author_email, author_href "
-               "FROM package_info WHERE package=%Q";
-       int ret;
-       char *query;
-       sqlite3_stmt *stmt;
-       int idx = 0;
-       author_x *info;
-
-       query = sqlite3_mprintf(query_raw, pkgid);
-       if (query == NULL) {
-               LOGE("out of memory");
-               return PMINFO_R_ERROR;
-       }
-
-       ret = sqlite3_prepare_v2(db, query, strlen(query),
-                       &stmt, NULL);
-       sqlite3_free(query);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(db));
-               return PMINFO_R_ERROR;
-       }
-
-       if (sqlite3_step(stmt) == SQLITE_ERROR) {
-               LOGE("step error: %s", sqlite3_errmsg(db));
-               sqlite3_finalize(stmt);
-               return PMINFO_R_ERROR;
-       }
-
-       /* one author per one package */
-       info = calloc(1, sizeof(author_x));
-       if (info == NULL) {
-               LOGE("out of memory");
-               sqlite3_finalize(stmt);
-               return PMINFO_R_ERROR;
-       }
-
-       _save_column_str(stmt, idx++, &info->text);
-       _save_column_str(stmt, idx++, &info->email);
-       _save_column_str(stmt, idx++, &info->href);
-
-       /* TODO: revised */
-       *author = g_list_append(*author, info);
-
-       sqlite3_finalize(stmt);
-
-       return PMINFO_R_OK;
-}
-
-static int _pkginfo_get_label(sqlite3 *db, const char *pkgid,
-               const char *locale, GList **label)
-{
-       static const char query_raw[] =
-               "SELECT package_label, package_locale "
-               "FROM package_localized_info "
-               "WHERE package=%Q AND package_locale IN (%Q, %Q)";
-       int ret;
-       char *query;
-       sqlite3_stmt *stmt;
-       int idx;
-       label_x *info;
-
-       query = sqlite3_mprintf(query_raw, pkgid, locale, DEFAULT_LOCALE);
-       if (query == NULL) {
-               LOGE("out of memory");
-               return PMINFO_R_ERROR;
-       }
-
-       ret = sqlite3_prepare_v2(db, query, strlen(query),
-                       &stmt, NULL);
-       sqlite3_free(query);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(db));
-               return PMINFO_R_ERROR;
-       }
-
-       while (sqlite3_step(stmt) == SQLITE_ROW) {
-               info = calloc(1, sizeof(label_x));
-               if (info == NULL) {
-                       LOGE("out of memory");
-                       sqlite3_finalize(stmt);
-                       return PMINFO_R_ERROR;
-               }
-               idx = 0;
-               _save_column_str(stmt, idx++, &info->text);
-               _save_column_str(stmt, idx++, &info->lang);
-               *label = g_list_append(*label, info);
-       }
-
-       sqlite3_finalize(stmt);
-
-       return PMINFO_R_OK;
-}
-
-static int _pkginfo_get_icon(sqlite3 *db, const char *pkgid, const char *locale,
-               GList **icon)
-{
-       static const char query_raw[] =
-               "SELECT package_icon, package_locale "
-               "FROM package_localized_info "
-               "WHERE package=%Q AND package_locale IN (%Q, %Q)";
-       int ret;
-       char *query;
-       sqlite3_stmt *stmt;
-       int idx;
-       icon_x *info;
-
-       query = sqlite3_mprintf(query_raw, pkgid, locale, DEFAULT_LOCALE);
-       if (query == NULL) {
-               LOGE("out of memory");
-               return PMINFO_R_ERROR;
-       }
-
-       ret = sqlite3_prepare_v2(db, query, strlen(query),
-                       &stmt, NULL);
-       sqlite3_free(query);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(db));
-               return PMINFO_R_ERROR;
-       }
-
-       while (sqlite3_step(stmt) == SQLITE_ROW) {
-               info = calloc(1, sizeof(icon_x));
-               if (info == NULL) {
-                       LOGE("out of memory");
-                       sqlite3_finalize(stmt);
-                       return PMINFO_R_ERROR;
-               }
-               idx = 0;
-               _save_column_str(stmt, idx++, &info->text);
-               _save_column_str(stmt, idx++, &info->lang);
-               *icon = g_list_append(*icon, info);
-       }
-
-       sqlite3_finalize(stmt);
-
-       return PMINFO_R_OK;
-}
-
-static int _pkginfo_get_description(sqlite3 *db, const char *pkgid,
-               const char *locale, GList **description)
+static int _pkginfo_add_description_info_into_list(const char *locale,
+               char *record, GList **description)
 {
-       static const char query_raw[] =
-               "SELECT package_description, package_locale "
-               "FROM package_localized_info "
-               "WHERE package=%Q AND package_locale IN (%Q, %Q)";
-       int ret;
-       char *query;
-       sqlite3_stmt *stmt;
-       int idx;
        description_x *info;
 
-       query = sqlite3_mprintf(query_raw, pkgid, locale, DEFAULT_LOCALE);
-       if (query == NULL) {
+       info = calloc(1, sizeof(description_x));
+       if (info == NULL) {
                LOGE("out of memory");
                return PMINFO_R_ERROR;
        }
-
-       ret = sqlite3_prepare_v2(db, query, strlen(query),
-                       &stmt, NULL);
-       sqlite3_free(query);
-       if (ret != SQLITE_OK) {
-               LOGE("prepare failed: %s", sqlite3_errmsg(db));
-               return PMINFO_R_ERROR;
-       }
-
-       while (sqlite3_step(stmt) == SQLITE_ROW) {
-               info = calloc(1, sizeof(description_x));
-               if (info == NULL) {
-                       LOGE("out of memory");
-                       sqlite3_finalize(stmt);
-                       return PMINFO_R_ERROR;
-               }
-               idx = 0;
-               _save_column_str(stmt, idx++, &info->text);
-               _save_column_str(stmt, idx++, &info->lang);
-               *description = g_list_append(*description, info);
-       }
-
-       sqlite3_finalize(stmt);
+       info->lang = strdup(locale);
+       info->text = record;
+       *description = g_list_append(*description, info);
 
        return PMINFO_R_OK;
 }
@@ -375,11 +170,12 @@ static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
                GList **privileges)
 {
        static const char query_raw[] =
-               "SELECT privilege FROM package_privilege_info WHERE package=%Q";
+               "SELECT DISTINCT privilege FROM package_privilege_info "
+               "WHERE package=%Q";
        int ret;
        char *query;
        sqlite3_stmt *stmt;
-       char *privilege;
+       privilege_x *privilege;
 
        query = sqlite3_mprintf(query_raw, pkgid);
        if (query == NULL) {
@@ -396,11 +192,11 @@ static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
        }
 
        while (sqlite3_step(stmt) == SQLITE_ROW) {
-               privilege = NULL;
-               _save_column_str(stmt, 0, &privilege);
-               if (privilege)
-                       *privileges = g_list_append(*privileges,
-                                       (gpointer)privilege);
+               privilege = calloc(1, sizeof(privilege_x));
+               _save_column_str(stmt, 0, &privilege->value);
+               _save_column_str(stmt, 1, &privilege->type);
+               *privileges = g_list_append(*privileges,
+                               (gpointer)privilege);
        }
 
        sqlite3_finalize(stmt);
@@ -501,14 +297,32 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
                "pi.storeclient_id, pi.mainapp_id, pi.package_url, "
                "pi.root_path, pi.csc_path, pi.package_nodisplay, "
                "pi.package_api_version, pi.package_support_disable, "
-               "pi.package_tep_name, pi.package_zip_mount_file "
-               "FROM package_info as pi ";
+               "pi.package_tep_name, pi.package_zip_mount_file, pi.external_path, "
+               "pi.package_support_mode";
+       static const char query_author[] =
+               ", pi.author_name, pi.author_email, pi.author_href";
+       static const char query_label[] =
+               ", COALESCE("
+               "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+               "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
+       static const char query_icon[] =
+               ", COALESCE("
+               "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+               "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
+       static const char query_description[] =
+               ", COALESCE("
+               "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+               "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
+       static const char query_from_clause[] = " FROM package_info as pi";
        int ret = PMINFO_R_ERROR;
        int idx = 0;
-       const char *dbpath;
+       int query_len = 0;
+       char *dbpath;
+       char *tmp_record = NULL;
        char *constraints = NULL;
        char query[MAX_QUERY_LEN] = { '\0' };
        package_x *info = NULL;
+       author_x *author = NULL;
        GList *bind_params = NULL;
        sqlite3 *db;
        sqlite3_stmt *stmt;
@@ -521,8 +335,10 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
        ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
        if (ret != SQLITE_OK) {
                _LOGD("failed to open db: %d", ret);
+               free(dbpath);
                return PMINFO_R_ERROR;
        }
+       free(dbpath);
 
        if (filter != NULL) {
                tmp_filter = filter;
@@ -537,6 +353,31 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
        /* add package_disable='false' clause by default */
        pkgmgrinfo_pkginfo_filter_add_bool(tmp_filter, PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false);
 
+       query_len = strlen(query_raw);
+       snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
+       if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
+               strncat(query, query_author, MAX_QUERY_LEN - query_len - 1);
+               query_len += strlen(query_author);
+       }
+       if (flag & PMINFO_PKGINFO_GET_LABEL) {
+               strncat(query, query_label, MAX_QUERY_LEN - query_len - 1);
+               query_len += strlen(query_label);
+               bind_params = g_list_append(bind_params, strdup(locale));
+       }
+       if (flag & PMINFO_PKGINFO_GET_ICON) {
+               strncat(query, query_icon, MAX_QUERY_LEN - query_len - 1);
+               query_len += strlen(query_icon);
+               bind_params = g_list_append(bind_params, strdup(locale));
+       }
+       if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
+               strncat(query, query_description, MAX_QUERY_LEN - query_len - 1);
+               query_len += strlen(query_description);
+               bind_params = g_list_append(bind_params, strdup(locale));
+       }
+
+       strncat(query, query_from_clause, MAX_QUERY_LEN - query_len - 1);
+       query_len += strlen(query_from_clause);
+
        ret = _get_filtered_query(tmp_filter, locale, &constraints, &bind_params);
        if (ret != PMINFO_R_OK) {
                LOGE("Failed to get WHERE clause");
@@ -544,9 +385,7 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
        }
 
        if (constraints)
-               snprintf(query, MAX_QUERY_LEN - 1, "%s%s", query_raw, constraints);
-       else
-               snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
+               strncat(query, constraints, MAX_QUERY_LEN - query_len - 1);
 
        ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
        if (ret != SQLITE_OK) {
@@ -599,22 +438,31 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
                _save_column_str(stmt, idx++, &info->support_disable);
                _save_column_str(stmt, idx++, &info->tep_name);
                _save_column_str(stmt, idx++, &info->zip_mount_file);
+               _save_column_str(stmt, idx++, &info->external_path);
+               _save_column_str(stmt, idx++, &info->support_mode);
                info->for_all_users =
                        strdup((uid != GLOBAL_USER) ? "false" : "true");
 
                if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
-                       if (_pkginfo_get_author(db, info->package,
-                                               &info->author)) {
+                       /* TODO : author should be retrieved at package_localized_info */
+                       author = calloc(1, sizeof(author_x));
+                       if (author == NULL) {
                                pkgmgrinfo_basic_free_package(info);
                                sqlite3_finalize(stmt);
                                sqlite3_close_v2(db);
                                return PMINFO_R_ERROR;
                        }
+                       _save_column_str(stmt, idx++, &author->text);
+                       _save_column_str(stmt, idx++, &author->email);
+                       _save_column_str(stmt, idx++, &author->href);
+                       info->author = g_list_append(info->author, author);
                }
 
                if (flag & PMINFO_PKGINFO_GET_LABEL) {
-                       if (_pkginfo_get_label(db, info->package, locale,
-                                               &info->label)) {
+                       tmp_record = NULL;
+                       _save_column_str(stmt, idx++, &tmp_record);
+
+                       if (_add_label_info_into_list(locale, tmp_record, &info->label)) {
                                pkgmgrinfo_basic_free_package(info);
                                sqlite3_finalize(stmt);
                                sqlite3_close_v2(db);
@@ -623,8 +471,9 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
                }
 
                if (flag & PMINFO_PKGINFO_GET_ICON) {
-                       if (_pkginfo_get_icon(db, info->package, locale,
-                                               &info->icon)) {
+                       tmp_record = NULL;
+                       _save_column_str(stmt, idx++, &tmp_record);
+                       if (_add_icon_info_into_list(locale, tmp_record, &info->icon)) {
                                pkgmgrinfo_basic_free_package(info);
                                sqlite3_finalize(stmt);
                                sqlite3_close_v2(db);
@@ -633,8 +482,10 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
                }
 
                if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
-                       if (_pkginfo_get_description(db, info->package, locale,
-                                               &info->description)) {
+                       tmp_record = NULL;
+                       _save_column_str(stmt, idx++, &tmp_record);
+                       if (_pkginfo_add_description_info_into_list(locale, tmp_record,
+                                       &info->description)) {
                                pkgmgrinfo_basic_free_package(info);
                                sqlite3_finalize(stmt);
                                sqlite3_close_v2(db);
@@ -652,6 +503,13 @@ static int _pkginfo_get_packages(uid_t uid, const char *locale,
                        }
                }
 
+               if (__pkginfo_check_installed_storage(info) != PMINFO_R_OK) {
+                       ret = PMINFO_R_ERROR;
+                       pkgmgrinfo_basic_free_package(info);
+                       info = NULL;
+                       continue;
+               }
+
                g_hash_table_insert(packages, (gpointer)info->package,
                                (gpointer)info);
        }
@@ -888,10 +746,11 @@ API int pkgmgrinfo_pkginfo_get_type(pkgmgrinfo_pkginfo_h handle, char **type)
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->type == NULL)
-               info->pkg_info->type = strdup("");
 
-       *type = (char *)info->pkg_info->type;
+       if (info->pkg_info->type == NULL)
+               *type = "";
+       else
+               *type = (char *)info->pkg_info->type;
 
        return PMINFO_R_OK;
 }
@@ -905,10 +764,11 @@ API int pkgmgrinfo_pkginfo_get_version(pkgmgrinfo_pkginfo_h handle, char **versi
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->version == NULL)
-               info->pkg_info->version = strdup("");
 
-       *version = (char *)info->pkg_info->version;
+       if (info->pkg_info->version == NULL)
+               *version = "";
+       else
+               *version = (char *)info->pkg_info->version;
 
        return PMINFO_R_OK;
 }
@@ -922,10 +782,11 @@ API int pkgmgrinfo_pkginfo_get_api_version(pkgmgrinfo_pkginfo_h handle, char **a
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->api_version == NULL)
-               info->pkg_info->api_version = strdup("");
 
-       *api_version = (char *)info->pkg_info->api_version;
+       if (info->pkg_info->api_version == NULL)
+               *api_version = "";
+       else
+               *api_version = (char *)info->pkg_info->api_version;
 
        return PMINFO_R_OK;
 }
@@ -954,10 +815,11 @@ API int pkgmgrinfo_pkginfo_get_zip_mount_file(pkgmgrinfo_pkginfo_h handle, char
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->zip_mount_file == NULL)
-               info->pkg_info->zip_mount_file = strdup("");
 
-       *zip_mount_file = (char *)info->pkg_info->zip_mount_file;
+       if (info->pkg_info->zip_mount_file == NULL)
+               *zip_mount_file = "";
+       else
+               *zip_mount_file = (char *)info->pkg_info->zip_mount_file;
 
        return PMINFO_R_OK;
 }
@@ -987,283 +849,98 @@ API int pkgmgrinfo_pkginfo_get_install_location(pkgmgrinfo_pkginfo_h handle, pkg
 API int pkgmgrinfo_pkginfo_get_package_size(pkgmgrinfo_pkginfo_h handle, int *size)
 {
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+       char *temp = NULL;
 
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
        retvm_if(size == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
 
-       if (info->pkg_info == NULL || info->pkg_info->package_size == NULL)
-               return PMINFO_R_ERROR;
-
-       *size = atoi((char *)info->pkg_info->package_size);
-
-       return PMINFO_R_OK;
-}
-
-API int pkgmgrinfo_pkginfo_get_total_size(pkgmgrinfo_pkginfo_h handle, int *size)
-{
-       char *pkgid;
-       char device_path[PKG_STRING_LEN_MAX] = { '\0', };
-       long long rw_size = 0;
-       long long ro_size = 0;
-       long long tmp_size = 0;
-       long long total_size = 0;
-       struct stat fileinfo;
-       int ret;
-
-       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
-       retvm_if(size == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-
-       ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
-       if (ret < 0)
+       if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
 
-       /* RW area */
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/bin", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               rw_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/info", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                       rw_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/res", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                       rw_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/data", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               rw_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/shared", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               rw_size += tmp_size;
-       }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/setting", PKG_RW_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               rw_size += tmp_size;
-               }
-       }
-
-       /* RO area */
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/bin", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/info", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/res", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/data", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/shared", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
-               }
-       }
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/setting", PKG_RO_PATH, pkgid);
-       if (lstat(device_path, &fileinfo) == 0) {
-               if (!S_ISLNK(fileinfo.st_mode)) {
-                       tmp_size = _pkgmgr_calculate_dir_size(device_path);
-                       if (tmp_size > 0)
-                               ro_size += tmp_size;
+       if (info->pkg_info->package_size == NULL) {
+               temp = strdup("");
+               if (temp == NULL) {
+                       _LOGE("out of memory");
+                       return PMINFO_R_ERROR;
+               } else {
+                       info->pkg_info->package_size = temp;
                }
        }
 
-       /* Total size */
-       total_size = rw_size + ro_size;
-       *size = (int)total_size;
-
-       return PMINFO_R_OK;
-}
-
-API int pkgmgrinfo_pkginfo_get_data_size(pkgmgrinfo_pkginfo_h handle, int *size)
-{
-       char *pkgid;
-       char device_path[PKG_STRING_LEN_MAX] = { '\0', };
-       long long total_size = 0;
-
-       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
-       retvm_if(size == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-
-       if (pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid) < 0)
-               return PMINFO_R_ERROR;
-
-       snprintf(device_path, PKG_STRING_LEN_MAX, "%s%s/data", PKG_RW_PATH, pkgid);
-       if (access(device_path, R_OK) == 0)
-               total_size = _pkgmgr_calculate_dir_size(device_path);
-       if (total_size < 0)
-               return PMINFO_R_ERROR;
-
-       *size = (int)total_size;
+       *size = atoi((char *)info->pkg_info->package_size);
 
        return PMINFO_R_OK;
 }
 
 API int pkgmgrinfo_pkginfo_get_icon(pkgmgrinfo_pkginfo_h handle, char **icon)
 {
-       const char *locale;
        icon_x *ptr;
-       GList *tmp;
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
 
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL");
        retvm_if(icon == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
 
-       locale = info->locale;
-       retvm_if(locale == NULL, PMINFO_R_ERROR, "manifest locale is NULL");
-
-       if (info->pkg_info == NULL)
+       if (info->pkg_info == NULL || info->pkg_info->icon == NULL)
                return PMINFO_R_ERROR;
 
-       for (tmp = info->pkg_info->icon; tmp; tmp = tmp->next) {
-               ptr = (icon_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               !strcasecmp(ptr->text, "(null)") ||
-                               strcmp(ptr->lang, locale))
-                       continue;
-               *icon = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
+       ptr = (icon_x *)info->pkg_info->icon->data;
+       if (ptr == NULL)
+               return PMINFO_R_ERROR;
 
-       locale = DEFAULT_LOCALE;
-       for (tmp = info->pkg_info->icon; tmp; tmp = tmp->next) {
-               ptr = (icon_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               strcmp(ptr->lang, locale))
-                       continue;
-               *icon = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
+       /* TODO : should we return empty string if there was no icon? */
+       if (ptr->text == NULL)
+               *icon = "";
+       else
+               *icon = ptr->text;
 
-       return PMINFO_R_ERROR;
+       return PMINFO_R_OK;
 }
 
 API int pkgmgrinfo_pkginfo_get_label(pkgmgrinfo_pkginfo_h handle, char **label)
 {
-       const char *locale;
        label_x *ptr;
-       GList *tmp;
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
 
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL");
        retvm_if(label == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL");
 
-       locale = info->locale;
-       retvm_if(locale == NULL, PMINFO_R_ERROR, "manifest locale is NULL");
+       if (info->pkg_info == NULL || info->pkg_info->label == NULL)
+               return PMINFO_R_ERROR;
 
-       for (tmp = info->pkg_info->label; tmp != NULL; tmp = tmp->next) {
-               ptr = (label_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               strcmp(ptr->lang, locale))
-                       continue;
-               *label = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
+       ptr = (label_x *)info->pkg_info->label->data;
+       if (ptr == NULL)
+               return PMINFO_R_ERROR;
 
-       locale = DEFAULT_LOCALE;
-       for (tmp = info->pkg_info->label; tmp != NULL; tmp = tmp->next) {
-               ptr = (label_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               strcmp(ptr->lang, locale))
-                       continue;
-               *label = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
+       /* TODO : should we return empty string if there was no label? */
+       if (ptr->text == NULL)
+               *label = "";
+       else
+               *label = ptr->text;
 
-       return PMINFO_R_ERROR;
+       return PMINFO_R_OK;
 }
 
 API int pkgmgrinfo_pkginfo_get_description(pkgmgrinfo_pkginfo_h handle, char **description)
 {
-       const char *locale;
        description_x *ptr;
-       GList *tmp;
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
 
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
        retvm_if(description == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
 
-       locale = info->locale;
-       retvm_if(locale == NULL, PMINFO_R_ERROR, "manifest locale is NULL");
+       if (info->pkg_info == NULL || info->pkg_info->description == NULL)
+               return PMINFO_R_ERROR;
 
-       for (tmp = info->pkg_info->description; tmp; tmp = tmp->next) {
-               ptr = (description_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               strcmp(ptr->lang, locale))
-                       continue;
-               *description = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
+       ptr = (description_x *)info->pkg_info->description->data;
+       if (ptr == NULL)
+               return PMINFO_R_ERROR;
 
-       locale = DEFAULT_LOCALE;
-       for (tmp = info->pkg_info->description; tmp; tmp = tmp->next) {
-               ptr = (description_x *)tmp->data;
-               if (ptr == NULL || ptr->text == NULL || ptr->lang == NULL ||
-                               strcmp(ptr->lang, locale))
-                       continue;
+       if (ptr->text == NULL)
+               *description = "";
+       else
                *description = (char *)ptr->text;
-               return PMINFO_R_OK;
-       }
 
-       return PMINFO_R_ERROR;
+       return PMINFO_R_OK;
 }
 
 API int pkgmgrinfo_pkginfo_get_author_name(pkgmgrinfo_pkginfo_h handle, char **author_name)
@@ -1280,10 +957,11 @@ API int pkgmgrinfo_pkginfo_get_author_name(pkgmgrinfo_pkginfo_h handle, char **a
        author = (author_x *)info->pkg_info->author->data;
        if (author == NULL)
                return PMINFO_R_ERROR;
-       if (author->text == NULL)
-               author->text = strdup("");
 
-       *author_name = (char *)author->text;
+       if (author->text == NULL)
+               *author_name = "";
+       else
+               *author_name = (char *)author->text;
 
        return PMINFO_R_OK;
 }
@@ -1302,10 +980,11 @@ API int pkgmgrinfo_pkginfo_get_author_email(pkgmgrinfo_pkginfo_h handle, char **
        author = (author_x *)info->pkg_info->author->data;
        if (author == NULL)
                return PMINFO_R_ERROR;
-       if (author->email == NULL)
-               author->email = strdup("");
 
-       *author_email = (char *)author->email;
+       if (author->email == NULL)
+               *author_email = "";
+       else
+               *author_email = (char *)author->email;
 
        return PMINFO_R_OK;
 }
@@ -1324,10 +1003,11 @@ API int pkgmgrinfo_pkginfo_get_author_href(pkgmgrinfo_pkginfo_h handle, char **a
        author = (author_x *)info->pkg_info->author->data;
        if (author == NULL)
                return PMINFO_R_ERROR;
-       if (author->href == NULL)
-               author->href = strdup("");
 
-       *author_href = (char *)author->href;
+       if (author->href == NULL)
+               *author_href = "";
+       else
+               *author_href = (char *)author->href;
 
        return PMINFO_R_OK;
 }
@@ -1342,9 +1022,9 @@ API int pkgmgrinfo_pkginfo_get_installed_storage(pkgmgrinfo_pkginfo_h handle, pk
        if (info->pkg_info == NULL || info->pkg_info->installed_storage == NULL)
                return PMINFO_R_ERROR;
 
-       if (strcmp(info->pkg_info->installed_storage,"installed_internal") == 0)
+       if (strcmp(info->pkg_info->installed_storage, "installed_internal") == 0)
                *storage = PMINFO_INTERNAL_STORAGE;
-       else if (strcmp(info->pkg_info->installed_storage,"installed_external") == 0)
+       else if (strcmp(info->pkg_info->installed_storage, "installed_external") == 0)
                *storage = PMINFO_EXTERNAL_STORAGE;
        else
                return PMINFO_R_ERROR;
@@ -1376,10 +1056,11 @@ API int pkgmgrinfo_pkginfo_get_storeclientid(pkgmgrinfo_pkginfo_h handle, char *
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->storeclient_id == NULL)
-               info->pkg_info->storeclient_id = strdup("");
 
-       *storeclientid = (char *)info->pkg_info->storeclient_id;
+       if (info->pkg_info->storeclient_id == NULL)
+               *storeclientid = "";
+       else
+               *storeclientid = (char *)info->pkg_info->storeclient_id;
 
        return PMINFO_R_OK;
 }
@@ -1408,120 +1089,15 @@ API int pkgmgrinfo_pkginfo_get_url(pkgmgrinfo_pkginfo_h handle, char **url)
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->package_url == NULL)
-               info->pkg_info->package_url = strdup("");
-
-       *url = (char *)info->pkg_info->package_url;
-
-       return PMINFO_R_OK;
-}
-
-API int pkgmgrinfo_pkginfo_get_size_from_xml(const char *manifest, int *size)
-{
-       const char *val = NULL;
-       const xmlChar *node;
-       xmlTextReaderPtr reader;
-       retvm_if(manifest == NULL, PMINFO_R_EINVAL, "Input argument is NULL\n");
-       retvm_if(size == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-
-       xmlInitParser();
-       reader = xmlReaderForFile(manifest, NULL, 0);
-
-       if (reader){
-               if (__child_element(reader, -1)) {
-                       node = xmlTextReaderConstName(reader);
-                       if (!node) {
-                               _LOGE("xmlTextReaderConstName value is NULL\n");
-                               xmlFreeTextReader(reader);
-                               xmlCleanupParser();
-                               return PMINFO_R_ERROR;
-                       }
-
-                       if (!strcmp(ASC_CHAR(node), "manifest")) {
-                               if (xmlTextReaderGetAttribute(reader, XML_CHAR("size")))
-                                       val = ASC_CHAR(xmlTextReaderGetAttribute(reader, XML_CHAR("size")));
-
-                               if (val) {
-                                       *size = atoi(val);
-                               } else {
-                                       *size = 0;
-                                       _LOGE("package size is not specified\n");
-                                       xmlFreeTextReader(reader);
-                                       xmlCleanupParser();
-                                       return PMINFO_R_ERROR;
-                               }
-                       } else {
-                               _LOGE("Unable to create xml reader\n");
-                               xmlFreeTextReader(reader);
-                               xmlCleanupParser();
-                               return PMINFO_R_ERROR;
-                       }
-               }
-       } else {
-               _LOGE("xmlReaderForFile value is NULL\n");
-               xmlCleanupParser();
-               return PMINFO_R_ERROR;
-       }
-
-       xmlFreeTextReader(reader);
-       xmlCleanupParser();
 
-       return PMINFO_R_OK;
-}
-
-API int pkgmgrinfo_pkginfo_get_location_from_xml(const char *manifest, pkgmgrinfo_install_location *location)
-{
-       const char *val = NULL;
-       const xmlChar *node;
-       xmlTextReaderPtr reader;
-       retvm_if(manifest == NULL, PMINFO_R_EINVAL, "Input argument is NULL\n");
-       retvm_if(location == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
-
-       xmlInitParser();
-       reader = xmlReaderForFile(manifest, NULL, 0);
-
-       if (reader) {
-               if ( __child_element(reader, -1)) {
-                       node = xmlTextReaderConstName(reader);
-                       if (!node) {
-                               _LOGE("xmlTextReaderConstName value is NULL\n");
-                               xmlFreeTextReader(reader);
-                               xmlCleanupParser();
-                               return PMINFO_R_ERROR;
-                       }
-
-                       if (!strcmp(ASC_CHAR(node), "manifest")) {
-                               if (xmlTextReaderGetAttribute(reader, XML_CHAR("install-location")))
-                                       val = ASC_CHAR(xmlTextReaderGetAttribute(reader, XML_CHAR("install-location")));
-
-                               if (val) {
-                                       if (strcmp(val, "internal-only") == 0)
-                                               *location = PMINFO_INSTALL_LOCATION_INTERNAL_ONLY;
-                                       else if (strcmp(val, "prefer-external") == 0)
-                                               *location = PMINFO_INSTALL_LOCATION_PREFER_EXTERNAL;
-                                       else
-                                               *location = PMINFO_INSTALL_LOCATION_AUTO;
-                               }
-                       } else {
-                               _LOGE("Unable to create xml reader\n");
-                               xmlFreeTextReader(reader);
-                               xmlCleanupParser();
-                               return PMINFO_R_ERROR;
-                       }
-               }
-       } else {
-               _LOGE("xmlReaderForFile value is NULL\n");
-               xmlCleanupParser();
-               return PMINFO_R_ERROR;
-       }
-
-       xmlFreeTextReader(reader);
-       xmlCleanupParser();
+       if (info->pkg_info->package_url == NULL)
+               *url = "";
+       else
+               *url = (char *)info->pkg_info->package_url;
 
        return PMINFO_R_OK;
 }
 
-
 API int pkgmgrinfo_pkginfo_get_root_path(pkgmgrinfo_pkginfo_h handle, char **path)
 {
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
@@ -1546,24 +1122,38 @@ API int pkgmgrinfo_pkginfo_get_csc_path(pkgmgrinfo_pkginfo_h handle, char **path
 
        if (info->pkg_info == NULL)
                return PMINFO_R_ERROR;
-       if (info->pkg_info->csc_path == NULL)
-               info->pkg_info->csc_path = strdup("");
 
-       *path = (char *)info->pkg_info->csc_path;
+       if (info->pkg_info->csc_path == NULL)
+               *path = "";
+       else
+               *path = (char *)info->pkg_info->csc_path;
 
        return PMINFO_R_OK;
 }
 
+API int pkgmgrinfo_pkginfo_get_support_mode(pkgmgrinfo_pkginfo_h handle, int *support_mode)
+{
+       retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
+       retvm_if(support_mode == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
+
+       pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
+       if (info->pkg_info->support_mode)
+               *support_mode = atoi(info->pkg_info->support_mode);
+       else
+               *support_mode = 0;
+
+       return PMINFO_R_OK;
+}
 
 API int pkgmgrinfo_pkginfo_is_accessible(pkgmgrinfo_pkginfo_h handle, bool *accessible)
 {
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL\n");
        retvm_if(accessible == NULL, PMINFO_R_EINVAL, "Argument supplied to hold return value is NULL\n");
 
-#if 0 //smack issue occured, check later
+#if 0 /* smack issue occured, check later */
        char *pkgid = NULL;
        pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
-       if (pkgid == NULL){
+       if (pkgid == NULL) {
                 _LOGD("invalid func parameters\n");
                 return PMINFO_R_ERROR;
        }
@@ -1573,13 +1163,13 @@ API int pkgmgrinfo_pkginfo_is_accessible(pkgmgrinfo_pkginfo_h handle, bool *acce
        char app_mmc_path[FILENAME_MAX] = { 0, };
        char app_dir_path[FILENAME_MAX] = { 0, };
        char app_mmc_internal_path[FILENAME_MAX] = { 0, };
-       snprintf(app_dir_path, FILENAME_MAX,"%s%s", PKG_INSTALLATION_PATH, pkgid);
-       snprintf(app_mmc_path, FILENAME_MAX,"%s%s", PKG_SD_PATH, pkgid);
-       snprintf(app_mmc_internal_path, FILENAME_MAX,"%s%s/.mmc", PKG_INSTALLATION_PATH, pkgid);
+       snprintf(app_dir_path, FILENAME_MAX, "%s%s", PKG_INSTALLATION_PATH, pkgid);
+       snprintf(app_mmc_path, FILENAME_MAX, "%s%s", PKG_SD_PATH, pkgid);
+       snprintf(app_mmc_internal_path, FILENAME_MAX, "%s%s/.mmc", PKG_INSTALLATION_PATH, pkgid);
 
        /*check whether application is in external memory or not */
        fp = fopen(app_mmc_path, "r");
-       if (fp == NULL){
+       if (fp == NULL) {
                _LOGD(" app path in external memory not accesible\n");
        } else {
                fclose(fp);
@@ -1590,7 +1180,6 @@ API int pkgmgrinfo_pkginfo_is_accessible(pkgmgrinfo_pkginfo_h handle, bool *acce
        }
 
        /*check whether application is in internal or not */
-       fp = fopen(app_dir_path, "r");
        if (fp == NULL) {
                _LOGD(" app path in internal memory not accesible\n");
                *accessible = 0;
@@ -1600,12 +1189,11 @@ API int pkgmgrinfo_pkginfo_is_accessible(pkgmgrinfo_pkginfo_h handle, bool *acce
                /*check whether the application is installed in SD card
                but SD card is not present*/
                fp = fopen(app_mmc_internal_path, "r");
-               if (fp == NULL){
+               if (fp == NULL) {
                        *accessible = 1;
                        _LOGD("pkgmgr_get_pkg_external_validation() : INTERNAL_MEM \n");
                        return PMINFO_R_OK;
-               }
-               else{
+               } else {
                        *accessible = 0;
                        _LOGD("pkgmgr_get_pkg_external_validation() : ERROR_MMC_STATUS \n");
                }
@@ -2007,7 +1595,7 @@ API int pkgmgrinfo_pkginfo_foreach_privilege(pkgmgrinfo_pkginfo_h handle,
        retvm_if(handle == NULL, PMINFO_R_EINVAL, "pkginfo handle is NULL");
        retvm_if(privilege_func == NULL, PMINFO_R_EINVAL, "Callback function is NULL");
        int ret;
-       const char *privilege;
+       privilege_x *privilege;
        GList *tmp;
        pkgmgr_pkginfo_x *info = (pkgmgr_pkginfo_x *)handle;
 
@@ -2015,10 +1603,10 @@ API int pkgmgrinfo_pkginfo_foreach_privilege(pkgmgrinfo_pkginfo_h handle,
                return PMINFO_R_ERROR;
 
        for (tmp = info->pkg_info->privileges; tmp; tmp = tmp->next) {
-               privilege = (const char *)tmp->data;
+               privilege = (privilege_x *)tmp->data;
                if (privilege == NULL)
                        continue;
-               ret = privilege_func(privilege, user_data);
+               ret = privilege_func(privilege->value, user_data);
                if (ret < 0)
                        break;
        }