Change global variables into static
[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 #define _GNU_SOURCE
25 #include <dirent.h>
26 #include <time.h>
27 #include <db-util.h>
28 #include <grp.h>
29 #include <pwd.h>
30
31 #include "app2sd_internals.h"
32
33 #define MAX_QUERY_LEN 4096
34 #define PASSWORD_LENGTH 64
35 #define BUFSIZE 4096
36
37 /*
38 ########### Internal APIs ##################
39  */
40
41 /*sqlite  db code*/
42 #define APP2SD_DB_FILE tzplatform_mkpath(TZ_SYS_DB, ".app2sd.db")
43 static sqlite3 *app2sd_db;
44 #define QUERY_CREATE_TABLE_APP2SD "CREATE TABLE IF NOT EXISTS app2sd_info " \
45         "(pkgid TEXT NOT NULL, password TEXT NOT NULL, " \
46         "filename TEXT NOT NULL, uid INTEGER, PRIMARY KEY(pkgid, uid))"
47
48 static int _app2sd_db_change_perm(const char *db_file)
49 {
50         char buf[BUFSIZE];
51         char pwuid_buf[1024];
52         char journal_file[BUFSIZE];
53         int fd;
54         char *files[3];
55         int ret, i;
56         uid_t uid = APPFW_UID;
57         struct passwd userinfo;
58         struct passwd *result;
59         files[0] = (char *)db_file;
60         files[1] = journal_file;
61         files[2] = NULL;
62         const char *err_str;
63
64         if (db_file == NULL)
65                 return -1;
66
67         if (getuid() != OWNER_ROOT) {
68                 _E("not allowed user");
69                 return -1;
70         }
71
72         snprintf(journal_file, sizeof(journal_file), "%s%s", db_file,
73                         "-journal");
74
75         ret = getpwuid_r(uid, &userinfo, pwuid_buf, sizeof(pwuid_buf), &result);
76         if (ret != 0 || result == NULL) {
77                 _E("user(%d) doesn't exist", uid);
78                 return -1;
79         }
80
81         for (i = 0; files[i]; i++) {
82                 fd = open(files[i], O_RDONLY);
83                 if (fd == -1) {
84                         err_str = strerror_r(errno, buf, sizeof(buf));
85                         _E("failed to open %s : %s", files[i], err_str);
86                         return -1;
87                 }
88
89                 ret = fchown(fd, uid, userinfo.pw_gid);
90                 if (ret == -1) {
91                         err_str = strerror_r(errno, buf, sizeof(buf));
92                         _E("failed to fchown %s %d.%d : %s", files[i], uid,
93                                         userinfo.pw_gid, err_str);
94                         close(fd);
95                         return -1;
96                 }
97
98                 ret = fchmod(fd, 0644);
99                 if (ret == -1) {
100                         err_str = strerror_r(errno, buf, sizeof(buf));
101                         _E("failed to fchmod %s : %s", files[i], err_str);
102                         close(fd);
103                         return -1;
104                 }
105                 close(fd);
106         }
107         return 0;
108 }
109
110 int _app2sd_initialize_db(void)
111 {
112         char *error_message = NULL;
113         int ret;
114         FILE *fp;
115
116         fp = fopen(APP2SD_DB_FILE, "r");
117         if (fp != NULL) {
118                 fclose(fp);
119                 ret = db_util_open(APP2SD_DB_FILE, &app2sd_db,
120                                 DB_UTIL_REGISTER_HOOK_METHOD);
121
122                 if (ret != SQLITE_OK) {
123                         _E("connect menu_db [%s] failed", 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         ret = sqlite3_exec(app2sd_db, QUERY_CREATE_TABLE_APP2SD, NULL, NULL,
139                         &error_message);
140         if (ret != SQLITE_OK) {
141                 _E("don't execute query = (%s), error message = (%s)",
142                                 QUERY_CREATE_TABLE_APP2SD, error_message);
143                 sqlite3_free(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;
158         const char *val;
159         sqlite3_stmt *stmt;
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                 sqlite3_free(query);
180                 return -1;
181         }
182
183         val = (const char *)sqlite3_column_text(stmt, 0);
184         ret = atoi(val);
185         sqlite3_finalize(stmt);
186         sqlite3_free(query);
187
188         return ret;
189 }
190
191 int _app2sd_set_info_in_db(const char *pkgid, const char *passwd,
192                 const char *loopback_device, uid_t uid)
193 {
194         char *error_message = NULL;
195         char *query;
196         int ret;
197
198         ret = _app2sd_check_existing_info(pkgid, uid);
199         if (ret < 0) {
200                 _E("failed to get existing info");
201                 return APP2EXT_ERROR_SQLITE_REGISTRY;
202         }
203
204         if (ret == 0)
205                 query = sqlite3_mprintf("insert into app2sd_info "
206                                 "(pkgid, password, filename, uid) "
207                                 "values (%Q, %Q, %Q, %d)",
208                                 pkgid, passwd, loopback_device, uid);
209         else
210                 query = sqlite3_mprintf("update app2sd_info "
211                                 "set password=%Q, filename=%Q "
212                                 "where pkgid=%Q and uid=%d",
213                                 passwd, loopback_device, pkgid, uid);
214
215         ret = sqlite3_exec(app2sd_db, query, NULL, NULL, &error_message);
216         if (ret != SQLITE_OK) {
217                 _E("failed to execute query(%s), error message(%s)",
218                                 query, error_message);
219                 sqlite3_free(query);
220                 sqlite3_free(error_message);
221                 return APP2EXT_ERROR_SQLITE_REGISTRY;
222         }
223         sqlite3_free(query);
224
225         return APP2EXT_SUCCESS;
226 }
227
228 int _app2sd_remove_info_from_db(const char *pkgid, uid_t uid)
229 {
230         char *error_message = NULL;
231         char *query;
232         int ret = 0;
233
234         query = sqlite3_mprintf("delete from app2sd_info " \
235                 "where pkgid=%Q and uid=%d", pkgid, uid);
236
237         ret = sqlite3_exec(app2sd_db, query, NULL, NULL, &error_message);
238         if (ret != SQLITE_OK) {
239                 _E("failed to execute query(%s), error message(%s)",
240                         query, error_message);
241                 sqlite3_free(query);
242                 sqlite3_free(error_message);
243                 return APP2EXT_ERROR_SQLITE_REGISTRY;
244         }
245         sqlite3_free(query);
246
247         return APP2EXT_SUCCESS;
248 }
249
250 int _app2sd_get_info_from_db(const char *filename, char **pkgid, uid_t *uid)
251 {
252         char *query = NULL;
253         sqlite3_stmt *stmt = NULL;
254         int ret = APP2EXT_SUCCESS;
255
256         _D("filename(%s)", filename);
257         query = sqlite3_mprintf("select * from app2sd_info " \
258                 "where filename=%Q", filename);
259         if (query == NULL) {
260                 _E("failed to make a query");
261                 return APP2EXT_ERROR_SQLITE_REGISTRY;
262         }
263
264         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
265         if (ret != SQLITE_OK) {
266                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
267                 sqlite3_free(query);
268                 *pkgid = NULL;
269                 *uid = 0;
270                 return APP2EXT_ERROR_SQLITE_REGISTRY;
271         }
272
273         ret = sqlite3_step(stmt);
274         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
275                 _W("no records found");
276                 ret = APP2EXT_SUCCESS;
277                 goto FINISH_OFF;
278         }
279
280         *pkgid = strdup((const char *)sqlite3_column_text(stmt, 0));
281         if (*pkgid == NULL) {
282                 _E("out of memory");
283                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
284                 goto FINISH_OFF;
285         }
286
287         *uid = sqlite3_column_int(stmt, 3);
288         if (*uid != GLOBAL_USER && *uid < REGULAR_USER) {
289                 _E("invalid uid");
290                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
291                 goto FINISH_OFF;
292         }
293
294         if (SQLITE_OK != sqlite3_finalize(stmt)) {
295                 _E("error : sqlite3_finalize");
296                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
297                 goto FINISH_OFF;
298         }
299         sqlite3_free(query);
300
301         return APP2EXT_SUCCESS;
302
303 FINISH_OFF:
304         if (*pkgid) {
305                 free(*pkgid);
306                 *pkgid = NULL;
307         }
308         *uid = 0;
309
310         sqlite3_finalize(stmt);
311         sqlite3_free(query);
312
313         return ret;
314 }
315
316 int _app2sd_get_foreach_info_from_db(app2sd_info_cb cb_func)
317 {
318         char *query = NULL;
319         sqlite3_stmt *stmt = NULL;
320         const char *pkgid = NULL;
321         int uid = 0;
322         int ret = 0;
323
324         query = sqlite3_mprintf("select * from app2sd_info");
325         if (query == NULL) {
326                 _E("failed to make a query");
327                 return APP2EXT_ERROR_SQLITE_REGISTRY;
328         }
329
330         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
331         if (ret != SQLITE_OK) {
332                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
333                 sqlite3_free(query);
334                 return APP2EXT_ERROR_SQLITE_REGISTRY;
335         }
336
337         ret = APP2EXT_SUCCESS;
338         while (sqlite3_step(stmt) == SQLITE_ROW) {
339                 pkgid = (const char *)sqlite3_column_text(stmt, 0);
340                 uid = sqlite3_column_int(stmt, 3);
341
342                 ret = cb_func(pkgid, (uid_t)uid);
343                 if (ret) {
344                         _E("app2sd info callback error");
345                         /* continue */
346                 }
347         }
348
349         if (SQLITE_OK != sqlite3_finalize(stmt)) {
350                 _E("error : sqlite3_finalize");
351                 ret = APP2EXT_ERROR_SQLITE_REGISTRY;
352         }
353         sqlite3_free(query);
354
355         return ret;
356 }
357
358 char *_app2sd_get_password_from_db(const char *pkgid, uid_t uid)
359 {
360         char *query = NULL;
361         char *passwd = NULL;
362         sqlite3_stmt *stmt = NULL;
363         int ret = 0;
364
365         query = sqlite3_mprintf("select password from app2sd_info " \
366                 "where pkgid=%Q and uid=%d", pkgid, uid);
367         if (query == NULL) {
368                 _E("failed to make a query");
369                 return NULL;
370         }
371
372         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
373         if (ret != SQLITE_OK) {
374                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
375                 sqlite3_free(query);
376                 return NULL;
377         }
378
379         ret = sqlite3_step(stmt);
380         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
381                 _W("no records found");
382                 goto FINISH_OFF;
383         }
384
385         passwd = strdup((const char *)sqlite3_column_text(stmt, 0));
386         if (!passwd) {
387                 _E("memory allocation failed");
388                 goto FINISH_OFF;
389         }
390         if (strlen(passwd) == 0) {
391                 _W("data is empty");
392                 goto FINISH_OFF;
393         }
394         if (SQLITE_OK != sqlite3_finalize(stmt)) {
395                 _E("error : sqlite3_finalize");
396                 goto FINISH_OFF;
397         }
398         sqlite3_free(query);
399
400         return passwd;
401
402 FINISH_OFF:
403         if (passwd)
404                 free(passwd);
405
406         sqlite3_finalize(stmt);
407         sqlite3_free(query);
408
409         return NULL;
410 }
411
412 char *_app2sd_get_filename_from_db(const char *pkgid, uid_t uid)
413 {
414         char *query = NULL;
415         char *filename = NULL;
416         sqlite3_stmt *stmt = NULL;
417         int ret = 0;
418
419         query = sqlite3_mprintf("select filename from app2sd_info " \
420                 "where pkgid=%Q and uid=%d", pkgid, uid);
421         if (query == NULL) {
422                 _E("failed to make a query");
423                 return NULL;
424         }
425
426         ret = sqlite3_prepare_v2(app2sd_db, query, strlen(query), &stmt, NULL);
427         if (ret != SQLITE_OK) {
428                 _E("prepare failed (%s)", sqlite3_errmsg(app2sd_db));
429                 sqlite3_free(query);
430                 return NULL;
431         }
432
433         ret = sqlite3_step(stmt);
434         if (ret != SQLITE_ROW || ret == SQLITE_DONE) {
435                 _W("no records found");
436                 goto FINISH_OFF;
437         }
438
439         filename = strdup((const char *)sqlite3_column_text(stmt, 0));
440         if (!filename) {
441                 _E("memory allocation failed");
442                 goto FINISH_OFF;
443         }
444         if (strlen(filename) == 0) {
445                 _W("data is empty");
446                 goto FINISH_OFF;
447         }
448         if (SQLITE_OK != sqlite3_finalize(stmt)) {
449                 _E("error : sqlite3_finalize");
450                 goto FINISH_OFF;
451         }
452         sqlite3_free(query);
453
454         return filename;
455
456 FINISH_OFF:
457         if (filename)
458                 free(filename);
459
460         sqlite3_finalize(stmt);
461         sqlite3_free(query);
462
463         return NULL;
464 }