#include <glib.h>
#include <sqlite3.h>
+#include <sys/smack.h>
#include <vconf.h>
#include <vconf-keys.h>
#include <unicode/uloc.h>
#include <cynara-client.h>
#include <stdio.h>
#include <fcntl.h>
+#include <pwd.h>
+
+#include <aul_widget.h>
#include "widget_errno.h"
#include "debug.h"
#define RESOLUTION_SECTION_NAME "resolution"
#define RESOLUTION_FORMAT "%dx%d"
+#define CREATE_WIDGET_TABLE " \
+PRAGMA user_version = 40; \
+PRAGMA journal_mode = PERSIST; \
+PRAGMA foreign_keys = ON; \
+BEGIN EXCLUSIVE TRANSACTION; \
+CREATE TABLE widget_class ( \
+ classid TEXT NOT NULL, \
+ update_period INTEGER DEFAULT 0, \
+ setup_appid TEXT, \
+ appid TEXT NOT NULL, \
+ pkgid TEXT NOT NULL, \
+ nodisplay INTEGER DEFAULT 0, \
+ max_instance INTEGER DEFAULT 0, \
+ prime INTEGER DEFAULT 0, \
+ PRIMARY KEY(classid) \
+); \
+CREATE TABLE support_size ( \
+ classid TEXT NOT NULL, \
+ preview TEXT NOT NULL, \
+ frame INTEGER DEFAULT 0, \
+ width INTEGER NOT NULL, \
+ height INTEGER NOT NULL, \
+ FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE \
+); \
+CREATE TABLE label ( \
+ classid TEXT NOT NULL, \
+ locale TEXT DEFAULT 'No Locale', \
+ label TEXT NOT NULL, \
+ FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE \
+); \
+CREATE TABLE icon ( \
+ classid TEXT NOT NULL, \
+ locale TEXT DEFAULT 'No Locale', \
+ icon TEXT NOT NULL, \
+ FOREIGN KEY(classid) REFERENCES widget_class (classid) ON DELETE CASCADE \
+); \
+COMMIT TRANSACTION; "
+
+#define DB_LABEL "User::Home"
+#define SET_SMACK_LABEL(x) \
+do { \
+ if (smack_setlabel((x), DB_LABEL, SMACK_LABEL_ACCESS)) \
+ _E("failed chsmack -a %s %s", DB_LABEL, x); \
+ else \
+ _D("chsmack -a %s %s", DB_LABEL, x); \
+} while (0)
+
+#define WIDGET_TBL_COUNT 4
+static char *_widget_table_list[WIDGET_TBL_COUNT] = {
+ "icon",
+ "label",
+ "support_size",
+ "widget_class"
+};
+
struct widget_instance_info_s {
int period;
bool exists;
static const char *_iso3lang;
static char _country[ULOC_COUNTRY_CAPACITY];
static char *_syslang;
+static bool _is_corrupted = false;
static inline bool _is_widget_feature_enabled(void)
{
return 0;
}
-static const char *_get_db_path(uid_t uid)
+static const char *_get_db_path(uid_t uid, bool is_init)
{
const char *path;
if (!_is_global(uid))
tzplatform_set_user(uid);
- path = tzplatform_mkpath(_is_global(uid) ?
- TZ_SYS_DB : TZ_USER_DB, ".widget.db");
+ if (is_init && !_is_global(uid)) {
+ path = tzplatform_mkpath(TZ_SYS_ETC,
+ "skel/.applications/dbspace/.widget.db");
+ } else {
+ path = tzplatform_mkpath(_is_global(uid) ?
+ TZ_SYS_DB : TZ_USER_DB, ".widget.db");
+ }
+ _E("%s", path);
tzplatform_reset_user();
return path;
}
+static int _check_integrity_cb(void *pid, int argc, char **argv,
+ char **not_used)
+{
+ if (strcmp(argv[0], "ok") == 0)
+ return 0;
+
+ _E("db integrity result fail : %s" , argv[0]);
+ _is_corrupted = true;
+ return -1;
+}
+
+static int _recover_db(sqlite3 *db, const char *path, uid_t uid)
+{
+ int ret;
+ char *errmsg = NULL;
+ struct passwd pwd;
+ struct passwd *result;
+ char buf[MAX_BUF_SIZE];
+ uid_t new_uid;
+ char journal_path[PATH_MAX];
+
+ _I("DB recovery process start");
+ if (db)
+ sqlite3_close(db);
+ unlink(path);
+
+ ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ if (ret == 0)
+ _E("no such user: %d", uid);
+ else
+ _E("getpwuid_r failed: %d", errno);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ ret = sqlite3_open_v2(path, &db,
+ SQLITE_OPEN_CREATE |SQLITE_OPEN_READWRITE,
+ NULL);
+ if (ret != SQLITE_OK) {
+ _E("Failed to open db[%d]", ret);
+ unlink(path);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ ret = sqlite3_exec(db, CREATE_WIDGET_TABLE, NULL, NULL, &errmsg);
+ sqlite3_close(db);
+ if (ret != SQLITE_OK) {
+ _E("Failed to exec query[%d][%s]", ret, errmsg);
+ sqlite3_free(errmsg);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ snprintf(journal_path, sizeof(journal_path), "%s-journal", path);
+ SET_SMACK_LABEL(path);
+ SET_SMACK_LABEL(journal_path);
+ if (pwd.pw_uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))
+ new_uid = 0;
+ else
+ new_uid = pwd.pw_uid;
+
+ ret = chown(path, new_uid, pwd.pw_gid);
+ if (ret == -1) {
+ _E("chown fail %s", path);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ ret = chown(journal_path, new_uid, pwd.pw_gid);
+ if (ret == -1) {
+ _E("chown fail %s", path);
+ return WIDGET_ERROR_FAULT;
+ }
+ _I("DB recovery process done");
+
+ return WIDGET_ERROR_NONE;
+}
+
+static int _integrity_check(sqlite3 *db)
+{
+ int ret;
+ char *errmsg = NULL;
+
+ ret = sqlite3_exec(db, "PRAGMA integrity_check",
+ _check_integrity_cb, NULL, &errmsg);
+ if (ret != SQLITE_OK || _is_corrupted) {
+ _E("Failed to exec query[%d][%s]", ret, errmsg);
+ if (errmsg)
+ sqlite3_free(errmsg);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ return WIDGET_ERROR_NONE;
+}
+
+static int _check_table_exist(sqlite3 *db)
+{
+ int ret;
+ char *val;
+ int idx = 0;
+ sqlite3_stmt *stmt;
+ const char query[] =
+ "SELECT name FROM sqlite_master WHERE type='table'" \
+ " ORDER BY name ASC";
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ _E("prepare error: %s", sqlite3_errmsg(db));
+ sqlite3_close_v2(db);
+ return WIDGET_ERROR_FAULT;
+ /* LCOV_EXCL_STOP */
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW && idx < WIDGET_TBL_COUNT) {
+ val = (char *)sqlite3_column_text(stmt, 0);
+ _I("%s : %s", _widget_table_list[idx], val);
+ if (strcmp(_widget_table_list[idx], val) != 0)
+ continue;
+ idx++;
+ }
+
+ sqlite3_finalize(stmt);
+ if (idx != WIDGET_TBL_COUNT) {
+ _E("wrong table count");
+ sqlite3_close_v2(db);
+ return WIDGET_ERROR_FAULT;
+ }
+
+ return WIDGET_ERROR_NONE;
+}
+
+static int _check_db_integrity(uid_t uid, bool is_init)
+{
+ int ret;
+ const char *path;
+ sqlite3 *db = NULL;
+
+ path = _get_db_path(uid, is_init);
+ if (path == NULL)
+ return WIDGET_ERROR_FAULT;
+
+ /* check table exist */
+ ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY, NULL);
+ if (ret != SQLITE_OK) {
+ /* LCOV_EXCL_START */
+ ret = _recover_db(db, path, uid);
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* check integrity */
+ ret = _integrity_check(db);
+ if (ret != WIDGET_ERROR_NONE) {
+ ret = _recover_db(db, path, uid);
+ return ret;
+ }
+
+ /* check table exist */
+ ret = _check_table_exist(db);
+ if (ret != WIDGET_ERROR_NONE) {
+ ret = _recover_db(db, path, uid);
+ return ret;
+ }
+
+ if (db)
+ sqlite3_close(db);
+
+ return WIDGET_ERROR_NONE;
+}
+
+EAPI int widget_service_check_db_integrity(bool is_init)
+{
+ int ret;
+
+ ret = _check_db_integrity(tzplatform_getuid(TZ_SYS_GLOBALAPP_USER),
+ is_init);
+ _I("check global app db result : %d", ret);
+
+ ret = _check_db_integrity(tzplatform_getuid(TZ_SYS_DEFAULT_USER),
+ is_init);
+ _I("check default user db result : %d", ret);
+
+ return WIDGET_ERROR_NONE;
+}
+
static sqlite3 *_open_db(uid_t uid)
{
int ret;
const char *path;
sqlite3 *db;
- path = _get_db_path(uid);
+ path = _get_db_path(uid, false);
if (path == NULL)
return NULL;