Revert "Revert "Adjust log level not to recognized an error always""
[platform/core/appfw/app2sd.git] / plugin / app2sd / server / app2sd_internals_registry.c
1 /*
2  * app2ext
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Garima Shrivastava<garima.s@samsung.com>
7  *      Jyotsna Dhumale <jyotsna.a@samsung.com>
8  *      Venkatesha Sarpangala <sarpangala.v@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <dirent.h>
25 #include <time.h>
26 #include <db-util.h>
27 #include <grp.h>
28 #include <pwd.h>
29
30 #include "app2sd_internals.h"
31
32 #define MAX_QUERY_LEN 4096
33 #define PASSWORD_LENGTH 64
34 #define BUFSIZE 4096
35
36 /*
37 ########### Internal APIs ##################
38  */
39
40 /*sqlite  db code*/
41 #define APP2SD_DB_FILE tzplatform_mkpath(TZ_SYS_DB, ".app2sd.db")
42 sqlite3 *app2sd_db;
43 #define QUERY_CREATE_TABLE_APP2SD "CREATE TABLE IF NOT EXISTS app2sd_info " \
44         "(pkgid TEXT NOT NULL, password TEXT NOT NULL, " \
45         "filename TEXT NOT NULL, uid INTEGER, PRIMARY KEY(pkgid, uid))"
46
47 static int _app2sd_db_change_perm(const char *db_file)
48 {
49         char buf[BUFSIZE];
50         char pwuid_buf[1024];
51         char journal_file[BUFSIZE];
52         int fd;
53         char *files[3];
54         int ret, i;
55         uid_t uid = APPFW_UID;
56         struct passwd userinfo, *result = NULL;
57         files[0] = (char *)db_file;
58         files[1] = journal_file;
59         files[2] = NULL;
60
61         if (db_file == NULL)
62                 return -1;
63
64         if (getuid() != OWNER_ROOT) {
65                 _E("not allowed user");
66                 return -1;
67         }
68
69         snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
70
71         ret = getpwuid_r(uid, &userinfo, pwuid_buf, sizeof(pwuid_buf), &result);
72         if (ret != 0 || result == NULL) {
73                 _E("user(%d) doesn't exist", uid);
74                 return -1;
75         }
76
77         for (i = 0; files[i]; i++) {
78                 fd = open(files[i], O_RDONLY);
79                 if (fd == -1) {
80                         if (strerror_r(errno, buf, sizeof(buf)))
81                                 strncpy(buf, "", BUFSIZE - 1);
82                         _E("failed to open %s : %s", files[i], buf);
83                         return -1;
84                 }
85
86                 ret = fchown(fd, uid, userinfo.pw_gid);
87                 if (ret == -1) {
88                         if (strerror_r(errno, buf, sizeof(buf)))
89                                 strncpy(buf, "", BUFSIZE - 1);
90                         _E("failed to fchown %s %d.%d : %s", files[i], uid,
91                                         userinfo.pw_gid, buf);
92                         close(fd);
93                         return -1;
94                 }
95
96                 ret = fchmod(fd, 0644);
97                 if (ret == -1) {
98                         if (strerror_r(errno, buf, sizeof(buf)))
99                                 strncpy(buf, "", BUFSIZE - 1);
100                         _E("failed to fchmod %s : %s", files[i], buf);
101                         close(fd);
102                         return -1;
103                 }
104                 close(fd);
105         }
106         return 0;
107 }
108
109 int _app2sd_initialize_db()
110 {
111         char *error_message = NULL;
112         int ret;
113         FILE *fp = NULL;
114
115         fp = fopen(APP2SD_DB_FILE, "r");
116         if (fp != NULL) {
117                 fclose(fp);
118                 ret = db_util_open(APP2SD_DB_FILE, &app2sd_db,
119                         DB_UTIL_REGISTER_HOOK_METHOD);
120
121                 if (ret != SQLITE_OK) {
122                         _E("connect menu_db [%s] failed",
123                                 APP2SD_DB_FILE);
124                         return -1;
125                 }
126                 return 0;
127         }
128
129         ret = db_util_open(APP2SD_DB_FILE, &app2sd_db,
130                  DB_UTIL_REGISTER_HOOK_METHOD);
131
132         if (ret != SQLITE_OK) {
133                 _E("connect menu_db [%s] failed",
134                         APP2SD_DB_FILE);
135                 return -1;
136         }
137
138         if (SQLITE_OK != sqlite3_exec(app2sd_db,
139                 QUERY_CREATE_TABLE_APP2SD, NULL, NULL,
140                 &error_message)) {
141                 _E("don't execute query = (%s), " \
142                         "error message = (%s)",
143                         QUERY_CREATE_TABLE_APP2SD, error_message);
144                 return -1;
145         }
146
147         if (_app2sd_db_change_perm(APP2SD_DB_FILE) < 0) {
148                 _E("failed to change permissions");
149                 return -1;
150         }
151
152         return 0;
153 }
154
155 static int _app2sd_check_existing_info(const char *pkgid, uid_t uid)
156 {
157         char *query = NULL;
158         const char *val = NULL;
159         sqlite3_stmt *stmt = NULL;
160         int ret = 0;
161
162         query = sqlite3_mprintf("select count(*) from app2sd_info " \
163                 "where pkgid=%Q and uid=%d", pkgid, uid);
164         if (query == NULL) {
165                 _E("failed to make a query");
166                 return -1;
167         }
168
169         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
170         if (ret != SQLITE_OK) {
171                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
172                 sqlite3_free(query);
173                 return -1;
174         }
175
176         if (sqlite3_step(stmt) != SQLITE_ROW) {
177                 _E("failed to step");
178                 sqlite3_finalize(stmt);
179                 return -1;
180         }
181
182         val = (const char *)sqlite3_column_text(stmt, 0);
183         ret = atoi(val);
184         sqlite3_finalize(stmt);
185
186         return ret;
187 }
188
189 int _app2sd_set_info_in_db(const char *pkgid, const char *passwd,
190                 const char *loopback_device, uid_t uid)
191 {
192         char *error_message = NULL;
193         char *query = NULL;
194         int ret = 0;
195
196         ret = _app2sd_check_existing_info(pkgid, uid);
197         if (ret < 0) {
198                 _E("failed to get existing info");
199                 return APP2EXT_ERROR_SQLITE_REGISTRY;
200         }
201
202         if (ret == 0)
203                 query = sqlite3_mprintf("insert into app2sd_info " \
204                         "(pkgid, password, filename, uid) values (%Q, %Q, %Q, %d)",
205                         pkgid, passwd, loopback_device, uid);
206         else
207                 query = sqlite3_mprintf("update app2sd_info " \
208                         "set password=%Q, filename=%Q where pkgid=%Q and uid=%d",
209                         passwd, loopback_device, pkgid, uid);
210
211         ret = sqlite3_exec(app2sd_db, query, NULL, NULL, &error_message);
212         if (ret != SQLITE_OK) {
213                 _E("failed to execute query(%s), error message(%s)",
214                         query, error_message);
215                 sqlite3_free(query);
216                 return APP2EXT_ERROR_SQLITE_REGISTRY;
217         }
218         sqlite3_free(query);
219
220         return APP2EXT_SUCCESS;
221 }
222
223 int _app2sd_remove_info_from_db(const char *pkgid, uid_t uid)
224 {
225         char *error_message = NULL;
226         char *query = NULL;
227         int ret = 0;
228
229         query = sqlite3_mprintf("delete from app2sd_info " \
230                 "where pkgid=%Q and uid=%d", pkgid, uid);
231
232         ret = sqlite3_exec(app2sd_db, query, NULL, NULL, &error_message);
233         if (ret != SQLITE_OK) {
234                 _E("failed to execute query(%s), error message(%s)",
235                         query, error_message);
236                 sqlite3_free(query);
237                 return APP2EXT_ERROR_SQLITE_REGISTRY;
238         }
239         sqlite3_free(query);
240
241         return APP2EXT_SUCCESS;
242 }
243
244 int _app2sd_get_info_from_db(const char *filename, char **pkgid, uid_t *uid)
245 {
246         char *query = NULL;
247         sqlite3_stmt *stmt = NULL;
248         int ret = APP2EXT_SUCCESS;
249
250         _D("filename(%s)", filename);
251         query = sqlite3_mprintf("select * from app2sd_info " \
252                 "where filename=%Q", filename);
253         if (query == NULL) {
254                 _E("failed to make a query");
255                 return APP2EXT_ERROR_SQLITE_REGISTRY;
256         }
257
258         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
259         if (ret != SQLITE_OK) {
260                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
261                 sqlite3_free(query);
262                 *pkgid = NULL;
263                 *uid = 0;
264                 return APP2EXT_ERROR_SQLITE_REGISTRY;
265         }
266
267         ret = sqlite3_step(stmt);
268         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
269                 _W("no records found");
270                 ret = APP2EXT_SUCCESS;
271                 goto FINISH_OFF;
272         }
273
274         *pkgid = strdup((const char *)sqlite3_column_text(stmt, 0));
275         if (*pkgid == NULL) {
276                 _E("out of memory");
277                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
278                 goto FINISH_OFF;
279         }
280
281         *uid = sqlite3_column_int(stmt, 3);
282         if (*uid != GLOBAL_USER && *uid < REGULAR_USER) {
283                 _E("invalid uid");
284                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
285                 goto FINISH_OFF;
286         }
287
288         if (SQLITE_OK != sqlite3_finalize(stmt)) {
289                 _E("error : sqlite3_finalize");
290                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
291                 goto FINISH_OFF;
292         }
293         sqlite3_free(query);
294
295         return APP2EXT_SUCCESS;
296
297 FINISH_OFF:
298         if (*pkgid) {
299                 free(*pkgid);
300                 *pkgid = NULL;
301         }
302         *uid = 0;
303
304         sqlite3_finalize(stmt);
305         sqlite3_free(query);
306
307         return ret;
308 }
309
310 int _app2sd_get_foreach_info_from_db(app2sd_info_cb cb_func)
311 {
312         char *query = NULL;
313         sqlite3_stmt *stmt = NULL;
314         const char *pkgid = NULL;
315         int uid = 0;
316         int ret = 0;
317
318         query = sqlite3_mprintf("select * from app2sd_info");
319         if (query == NULL) {
320                 _E("failed to make a query");
321                 return APP2EXT_ERROR_SQLITE_REGISTRY;
322         }
323
324         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
325         if (ret != SQLITE_OK) {
326                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
327                 sqlite3_free(query);
328                 return APP2EXT_ERROR_SQLITE_REGISTRY;
329         }
330
331         ret = APP2EXT_SUCCESS;
332         while (sqlite3_step(stmt) == SQLITE_ROW) {
333                 pkgid = (const char *)sqlite3_column_text(stmt, 0);
334                 uid = sqlite3_column_int(stmt, 3);
335
336                 ret = cb_func(pkgid, (uid_t)uid);
337                 if (ret) {
338                         _E("app2sd info callback error");
339                         /* continue */
340                 }
341         }
342
343         if (SQLITE_OK != sqlite3_finalize(stmt)) {
344                 _E("error : sqlite3_finalize");
345                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
346         }
347         sqlite3_free(query);
348
349         return ret;
350 }
351
352 char *_app2sd_get_password_from_db(const char *pkgid, uid_t uid)
353 {
354         char *query = NULL;
355         char *passwd = NULL;
356         sqlite3_stmt *stmt = NULL;
357         int ret = 0;
358
359         query = sqlite3_mprintf("select password from app2sd_info " \
360                 "where pkgid=%Q and uid=%d", pkgid, uid);
361         if (query == NULL) {
362                 _E("failed to make a query");
363                 return NULL;
364         }
365
366         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
367         if (ret != SQLITE_OK) {
368                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
369                 sqlite3_free(query);
370                 return NULL;
371         }
372
373         ret = sqlite3_step(stmt);
374         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
375                 _W("no records found");
376                 goto FINISH_OFF;
377         }
378
379         passwd = strdup((const char *)sqlite3_column_text(stmt, 0));
380         if (!passwd) {
381                 _E("memory allocation failed");
382                 goto FINISH_OFF;
383         }
384         if (strlen(passwd) == 0) {
385                 _W("data is empty");
386                 goto FINISH_OFF;
387         }
388         if (SQLITE_OK != sqlite3_finalize(stmt)) {
389                 _E("error : sqlite3_finalize");
390                 goto FINISH_OFF;
391         }
392         sqlite3_free(query);
393
394         return passwd;
395
396 FINISH_OFF:
397         if (passwd)
398                 free(passwd);
399
400         sqlite3_finalize(stmt);
401         sqlite3_free(query);
402
403         return NULL;
404 }
405
406 char *_app2sd_get_filename_from_db(const char *pkgid, uid_t uid)
407 {
408         char *query = NULL;
409         char *filename = NULL;
410         sqlite3_stmt *stmt = NULL;
411         int ret = 0;
412
413         query = sqlite3_mprintf("select filename from app2sd_info " \
414                 "where pkgid=%Q and uid=%d", pkgid, uid);
415         if (query == NULL) {
416                 _E("failed to make a query");
417                 return NULL;
418         }
419
420         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
421         if (ret != SQLITE_OK) {
422                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
423                 sqlite3_free(query);
424                 return NULL;
425         }
426
427         ret = sqlite3_step(stmt);
428         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
429                 _W("no records found");
430                 goto FINISH_OFF;
431         }
432
433         filename = strdup((const char *)sqlite3_column_text(stmt, 0));
434         if (!filename) {
435                 _E("memory allocation failed");
436                 goto FINISH_OFF;
437         }
438         if (strlen(filename) == 0) {
439                 _W("data is empty");
440                 goto FINISH_OFF;
441         }
442         if (SQLITE_OK != sqlite3_finalize(stmt)) {
443                 _E("error : sqlite3_finalize");
444                 goto FINISH_OFF;
445         }
446         sqlite3_free(query);
447
448         return filename;
449
450 FINISH_OFF:
451         if (filename)
452                 free(filename);
453
454         sqlite3_finalize(stmt);
455         sqlite3_free(query);
456
457         return NULL;
458 }