Release Version 0.4.0
[platform/core/appfw/pkgmgr-server.git] / src / restriction_mode.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <linux/limits.h>
10
11 #include <sqlite3.h>
12
13 #include "pkgmgr-server.h"
14
15 #ifndef RUN_DIR
16 #define RUN_DIR "/run/user"
17 #endif
18 #ifndef DB_DIR
19 #define DB_DIR "/var/lib/package-manager"
20 #endif
21 #define RESTRICTION_CONF ".package_manager_restriction_mode"
22 #define BUFSIZE 4096
23
24 static int __set_mode(int cur, int mode)
25 {
26         return cur | mode;
27 }
28
29 static int __unset_mode(int cur, int mode)
30 {
31         return cur & ~(mode);
32 }
33
34 static char *__get_conf_file_path(uid_t uid)
35 {
36         char buf[PATH_MAX];
37
38         snprintf(buf, sizeof(buf), "%s/%d/%s", RUN_DIR, uid, RESTRICTION_CONF);
39
40         return strdup(buf);
41 }
42
43 static int __set_restriction_mode(uid_t uid, int mode)
44 {
45         char *conf_path;
46         int fd;
47         int cur = 0;
48         ssize_t len;
49
50         conf_path = __get_conf_file_path(uid);
51         if (conf_path == NULL) {
52                 ERR("failed to get conf path");
53                 return -1;
54         }
55
56         fd = open(conf_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
57         if (fd < 0) {
58                 ERR("failed to open conf file: %d", errno);
59                 free(conf_path);
60                 return -1;
61         }
62
63         len = read(fd, &cur, sizeof(int));
64         if (len < 0) {
65                 ERR("failed to read conf file: %d", errno);
66                 close(fd);
67                 free(conf_path);
68                 return -1;
69         }
70
71         mode = __set_mode(cur, mode);
72
73         lseek(fd, 0, SEEK_SET);
74         len = write(fd, &mode, sizeof(int));
75         if (len < 0) {
76                 ERR("failed to write conf file: %d", errno);
77                 close(fd);
78                 free(conf_path);
79                 return -1;
80         }
81
82         close(fd);
83         free(conf_path);
84
85         return 0;
86 }
87
88 static int __unset_restriction_mode(uid_t uid, int mode)
89 {
90         char *conf_path;
91         int fd;
92         int cur = 0;
93         ssize_t len;
94
95         conf_path = __get_conf_file_path(uid);
96         if (conf_path == NULL) {
97                 ERR("failed to get conf path");
98                 return -1;
99         }
100
101         if (access(conf_path, F_OK) != 0) {
102                 free(conf_path);
103                 return 0;
104         }
105
106         fd = open(conf_path, O_RDWR, 0);
107         if (fd < 0) {
108                 ERR("failed to open conf file: %s", errno);
109                 free(conf_path);
110                 return -1;
111         }
112
113         len = read(fd, &cur, sizeof(int));
114         if (len < 0) {
115                 ERR("failed to read conf file: %d", errno);
116                 close(fd);
117                 free(conf_path);
118                 return -1;
119         }
120
121         mode = __unset_mode(cur, mode);
122
123         lseek(fd, 0, SEEK_SET);
124         len = write(fd, &mode, sizeof(int));
125         if (len < 0) {
126                 ERR("failed to write conf file: %d", errno);
127                 close(fd);
128                 free(conf_path);
129                 return -1;
130         }
131
132         close(fd);
133         free(conf_path);
134
135         return 0;
136 }
137
138 static int __get_restriction_mode(uid_t uid, int *mode)
139 {
140         char *conf_path;
141         int fd;
142         int cur;
143         ssize_t len;
144
145         conf_path = __get_conf_file_path(uid);
146         if (conf_path == NULL)
147                 return -1;
148
149         if (access(conf_path, F_OK) != 0) {
150                 free(conf_path);
151                 *mode = 0;
152                 return 0;
153         }
154
155         fd = open(conf_path, O_RDONLY, 0);
156         if (fd < 0) {
157                 ERR("failed to open conf file: %s", errno);
158                 free(conf_path);
159                 return -1;
160         }
161
162         len = read(fd, &cur, sizeof(int));
163         if (len < 0) {
164                 ERR("failed to read conf file: %d", errno);
165                 close(fd);
166                 free(conf_path);
167                 return -1;
168         }
169
170         *mode = cur;
171
172         close(fd);
173         free(conf_path);
174
175         return 0;
176 }
177
178 static const char *__get_db_path(void)
179 {
180         return DB_DIR"/restriction.db";
181 }
182
183 static sqlite3 *__open_db(void)
184 {
185         int ret;
186         const char *path;
187         sqlite3 *db;
188
189         path = __get_db_path();
190         if (path == NULL) {
191                 ERR("get db path error");
192                 return NULL;
193         }
194
195         ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
196         if (ret != SQLITE_OK) {
197                 ERR("open db error: %d", ret);
198                 return NULL;
199         }
200
201         return db;
202 }
203
204 enum {
205         TYPE_SET,
206         TYPE_UNSET,
207 };
208
209 static int __update_pkg_restriction_mode(uid_t uid, const char *pkgid, int mode,
210                 int type)
211 {
212         static const char query[] =
213                 "INSERT OR REPLACE INTO restriction (uid, pkgid, mode) "
214                 "VALUES(?, ?, (COALESCE("
215                 " (SELECT mode FROM restriction WHERE uid=? AND pkgid=?), 0) ";
216         int ret;
217         sqlite3 *db;
218         sqlite3_stmt *stmt;
219         char buf[BUFSIZE];
220
221         db = __open_db();
222         if (db == NULL)
223                 return -1;
224
225         snprintf(buf, sizeof(buf), "%s%s", query,
226                         type == TYPE_SET ? "| ?))" : "& ~?))");
227
228         ret = sqlite3_prepare_v2(db, buf, strlen(buf), &stmt, NULL);
229         if (ret != SQLITE_OK) {
230                 ERR("prepare error: %s", sqlite3_errmsg(db));
231                 sqlite3_close_v2(db);
232                 return -1;
233         }
234
235         sqlite3_bind_int(stmt, 1, uid);
236         sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_STATIC);
237         sqlite3_bind_int(stmt, 3, uid);
238         sqlite3_bind_text(stmt, 4, pkgid, -1, SQLITE_STATIC);
239         sqlite3_bind_int(stmt, 5, mode);
240
241         ret = sqlite3_step(stmt);
242         sqlite3_finalize(stmt);
243         if (ret != SQLITE_DONE) {
244                 ERR("step error: %s", sqlite3_errmsg(db));
245                 sqlite3_close_v2(db);
246                 return -1;
247         }
248
249         sqlite3_close_v2(db);
250
251         return 0;
252 }
253
254 static int __get_pkg_restriction_mode(uid_t uid, const char *pkgid, int *mode)
255 {
256         static const char query[] =
257                 "SELECT COALESCE( "
258                 " (SELECT mode FROM restriction WHERE uid=? AND pkgid=?), 0)";
259         int ret;
260         sqlite3 *db;
261         sqlite3_stmt *stmt;
262
263         db = __open_db();
264         if (db == NULL)
265                 return -1;
266
267         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
268         if (ret != SQLITE_OK) {
269                 ERR("prepare error: %s", sqlite3_errmsg(db));
270                 sqlite3_close_v2(db);
271                 return -1;
272         }
273
274         sqlite3_bind_int(stmt, 1, uid);
275         sqlite3_bind_text(stmt, 2, pkgid, -1, SQLITE_STATIC);
276
277         ret = sqlite3_step(stmt);
278         if (ret != SQLITE_ROW) {
279                 ERR("step error: %s", sqlite3_errmsg(db));
280                 sqlite3_finalize(stmt);
281                 sqlite3_close_v2(db);
282                 return -1;
283         }
284
285         *mode = sqlite3_column_int(stmt, 0);
286
287         sqlite3_finalize(stmt);
288         sqlite3_close_v2(db);
289
290         return 0;
291 }
292
293 int _set_restriction_mode(uid_t uid, const char *pkgid, int mode)
294 {
295         if (pkgid && strlen(pkgid))
296                 return __update_pkg_restriction_mode(uid, pkgid, mode,
297                                 TYPE_SET);
298         else
299                 return __set_restriction_mode(uid, mode);
300 }
301
302 int _unset_restriction_mode(uid_t uid, const char *pkgid, int mode)
303 {
304         if (pkgid && strlen(pkgid))
305                 return __update_pkg_restriction_mode(uid, pkgid, mode,
306                                 TYPE_UNSET);
307         else
308                 return __unset_restriction_mode(uid, mode);
309 }
310
311 int _get_restriction_mode(uid_t uid, const char *pkgid, int *mode)
312 {
313         if (pkgid && strlen(pkgid))
314                 return __get_pkg_restriction_mode(uid, pkgid, mode);
315         else
316                 return __get_restriction_mode(uid, mode);
317 }