2 * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
4 * Contact: Junghyun Yeon <jungh.yeon@samsung.com>,
5 * Jongmyeong Ko <jongmyeong.ko@samsung.com>, Sangyoon Jang <s89.jang@samsung.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
32 #include <sys/types.h>
38 #include <tzplatform_config.h>
40 #include <pkgmgr_parser_db.h>
43 #define APPFW_USER "app_fw"
48 #define REGULAR_USER 5000
49 #define MAX_QUERY_LEN 4096
52 #define PKGMGR_PARSER_DB_FILE tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_parser.db")
53 #define PKGMGR_CERT_DB_FILE tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_cert.db")
55 typedef struct user_info {
60 static GList *user_info_list;
62 static char *__get_dbpath(uid_t uid)
67 db_path = tzplatform_getenv(TZ_SYS_DB);
68 if (db_path == NULL) {
69 printf("Failed to get TZ_SYS_DB path");
73 snprintf(path, sizeof(path), "%s/user/%d/.pkgmgr_parser.db", db_path, uid);
77 static bool __integrity_check(const char *db_path)
80 sqlite3_stmt *stmt = NULL;
81 const char *check_result;
82 static const char integrity_check_query[] =
83 "PRAGMA integrity_check";
86 ret = sqlite3_open_v2(db_path, &db,
87 SQLITE_OPEN_READWRITE, NULL);
88 if (ret != SQLITE_OK) {
89 printf("Failed to open db\n");
93 ret = sqlite3_prepare_v2(db, integrity_check_query,
94 strlen(integrity_check_query), &stmt, NULL);
95 if (ret != SQLITE_OK) {
96 printf("Failed to check integrity_check : %s\n", sqlite3_errmsg(db));
100 ret = sqlite3_step(stmt);
101 if (ret != SQLITE_ROW) {
102 printf("Failed to check integrity db :%s\n", sqlite3_errmsg(db));
106 check_result = (const char *)sqlite3_column_text(stmt, 0);
108 printf("Failed to check integrity db :%s\n", sqlite3_errmsg(db));
112 if (strcasecmp(check_result, "ok") != 0) {
113 printf("db corrupted :%s\n", db_path);
117 sqlite3_finalize(stmt);
122 sqlite3_finalize(stmt);
127 static bool __change_owner(const char *files[2], uid_t uid)
133 struct passwd *result;
138 if (uid == OWNER_ROOT) {
139 ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
140 if (result == NULL) {
142 printf("no such user: %d\n", uid);
144 printf("getpwnam_r failed: %d", errno);
150 ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
151 if (result == NULL) {
153 printf("no such user: %d\n", uid);
155 printf("getpwuid_r failed: %d\n", errno);
159 for (i = 0; i < 2; i++) {
160 fd = open(files[i], O_RDONLY);
162 printf("open %s failed: %d\n", files[i], errno);
165 ret = fstat(fd, &sb);
167 printf("stat %s failed: %d\n", files[i], errno);
171 if (S_ISLNK(sb.st_mode)) {
172 printf("%s is symlink!\n", files[i]);
176 ret = fchown(fd, uid, pwd.pw_gid);
178 printf("fchown %s failed: %d\n", files[i], errno);
183 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
184 if (strstr(files[0], PKGMGR_CERT_DB_FILE) != NULL)
186 ret = fchmod(fd, mode);
188 printf("fchmod %s failed: %d\n", files[i], errno);
198 static void __change_permission(uid_t uid)
200 const char *files[2];
201 char *parser_dbpath = NULL;
202 char journal_file[PATH_MAX];
206 if (uid < REGULAR_USER) {
207 files[0] = PKGMGR_PARSER_DB_FILE;
208 snprintf(journal_file, sizeof(journal_file),
209 "%s-journal", PKGMGR_PARSER_DB_FILE);
210 files[1] = journal_file;
212 if (!__change_owner(files, uid)) {
213 printf("Failed to change ownership\n");
217 files[0] = PKGMGR_CERT_DB_FILE;
218 snprintf(journal_file, sizeof(journal_file),
219 "%s-journal", PKGMGR_CERT_DB_FILE);
220 files[1] = journal_file;
221 if (!__change_owner(files, uid)) {
222 printf("Failed to change ownership\n");
226 for (tmp_list = user_info_list; tmp_list != NULL;
227 tmp_list = g_list_next(tmp_list)) {
228 tmp_info = (user_info *)tmp_list->data;
232 if (tmp_info->uid == uid) {
233 parser_dbpath = tmp_info->db_path;
237 files[0] = parser_dbpath;
238 snprintf(journal_file, sizeof(journal_file),
239 "%s-journal", parser_dbpath);
240 files[1] = journal_file;
242 if (!__change_owner(files, uid)) {
243 printf("Failed to change ownership\n");
249 static void _xsystem(const char *argv[])
257 perror("fork failed");
261 execvp(argv[0], (char *const *)argv);
267 if (waitpid(pid, &status, 0) == -1) {
268 perror("waitpid failed");
271 if (WIFSIGNALED(status)) {
275 if (!WIFEXITED(status)) {
276 /* shouldn't happen */
277 perror("should not happen");
282 static void __create_db(uid_t uid)
285 const char *create_db[] = { "/usr/bin/pkg-db-creator", uid_string, NULL};
287 snprintf(uid_string, sizeof(uid_string), "%d", (int)uid);
291 static void __initdb(uid_t uid)
294 const char *initdb_rw[] = { "/usr/bin/pkg_initdb",
295 "--recover-db", "--uid", uid_string, "--keep-db", NULL};
296 const char *initdb_ro[] = { "/usr/bin/pkg_initdb",
297 "--recover-db", "--keep-db", NULL};
300 __change_permission(uid);
301 snprintf(uid_string, sizeof(uid_string), "%d", (int)uid);
302 _xsystem((uid > REGULAR_USER) ? initdb_rw : initdb_ro);
305 static void __initdb_all()
307 GList *tmp_list = NULL;
311 for (tmp_list = user_info_list;
312 tmp_list != NULL; tmp_list = g_list_next(tmp_list)) {
313 tmp_info = (user_info *)tmp_list->data;
314 if (!tmp_info || tmp_info->uid < REGULAR_USER)
316 __initdb(tmp_info->uid);
320 static void __check_user_db()
322 GList *tmp_list = NULL;
325 for (tmp_list = user_info_list;
326 tmp_list != NULL; tmp_list = g_list_next(tmp_list)) {
327 tmp_info = (user_info *)tmp_list->data;
330 if (!__integrity_check(tmp_info->db_path)) {
331 printf("User db for %d has corrupted\n", (int)tmp_info->uid);
332 __initdb(tmp_info->uid);
337 static void _free_user_info(gpointer data)
339 user_info *info = (user_info *)data;
344 static void _get_user_list()
349 char traverse_path[PATH_MAX];
350 char abs_dirname[PATH_MAX];
355 db_path = tzplatform_getenv(TZ_SYS_DB);
356 if (db_path == NULL) {
357 printf("Failed to get TZ_SYS_DB path");
361 snprintf(traverse_path, sizeof(traverse_path), "%s/user", db_path);
362 dir = opendir(traverse_path);
364 while ((ent = readdir(dir)) != NULL) {
365 snprintf(abs_dirname, PATH_MAX, "%s/%s", traverse_path,
367 stat(abs_dirname, &stats);
368 if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name) ||
369 !S_ISDIR(stats.st_mode))
371 info = calloc(1, sizeof(user_info));
377 uid = (uid_t)atoi(ent->d_name);
383 info->db_path = __get_dbpath(uid);
384 user_info_list = g_list_append(user_info_list, info);
390 static void _check_db()
392 if (!__integrity_check(PKGMGR_CERT_DB_FILE)) {
393 printf("Cert db corrupted. restore entire pkgmgr db\n");
396 } else if (!__integrity_check(PKGMGR_PARSER_DB_FILE)) {
397 printf("Global parser db corrupted. restore entire pkgmgr db\n");
405 int main(int argc, char *argv[])
407 if ((int)getuid() > REGULAR_USER) {
408 printf("This cmd is not allowed for regular user\n");
415 g_list_free_full(user_info_list, _free_user_info);