Implement pkgmgrinfo_pkginfo_set_installed_storage
[platform/core/appfw/pkgmgr-info.git] / src / pkgmgrinfo_db.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <grp.h>
11 #include <dirent.h>
12 #include <libgen.h>
13
14 #include <sqlite3.h>
15
16 #include <tzplatform_config.h>
17
18 #include "pkgmgr-info.h"
19 #include "pkgmgrinfo_debug.h"
20 #include "pkgmgrinfo_private.h"
21 #include "pkgmgr_parser.h"
22 #include "pkgmgr_parser_db.h"
23 #include "manager/pkginfo_manager.h"
24
25 typedef int (*sqlite_query_callback)(void *data, int ncols, char **coltxt, char **colname);
26
27 static int _mkdir_for_user(const char* dir, uid_t uid, gid_t gid)
28 {
29         int ret;
30         char *fullpath;
31         char *subpath;
32         char buf[1024];
33         int fd;
34         struct stat sb;
35
36         fullpath = strdup(dir);
37         if (fullpath == NULL)
38                 return -1;
39         subpath = dirname(fullpath);
40         if (strlen(subpath) > 1 && strcmp(subpath, fullpath) != 0) {
41                 ret = _mkdir_for_user(fullpath, uid, gid);
42                 if (ret == -1) {
43                         free(fullpath);
44                         return ret;
45                 }
46         }
47
48         ret = mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
49         if (ret && errno != EEXIST) {
50                 free(fullpath);
51                 return ret;
52         } else if (ret && errno == EEXIST) {
53                 free(fullpath);
54                 return 0;
55         }
56
57         if (getuid() == ROOT_UID) {
58                 fd = open(dir, O_RDONLY);
59                 if (fd == -1) {
60                         _LOGE("FAIL : open %s : %s", dir,
61                                         strerror_r(errno, buf, sizeof(buf)));
62                         free(fullpath);
63                         return -1;
64                 }
65                 ret = fstat(fd, &sb);
66                 if (ret == -1) {
67                         _LOGE("FAIL : fstat %s : %s", dir,
68                                         strerror_r(errno, buf, sizeof(buf)));
69                         close(fd);
70                         free(fullpath);
71                         return -1;
72                 }
73                 if (S_ISLNK(sb.st_mode)) {
74                         _LOGE("FAIL : %s is symlink!", dir);
75                         close(fd);
76                         free(fullpath);
77                         return -1;
78                 }
79                 ret = fchown(fd, uid, gid);
80                 if (ret == -1) {
81                         _LOGE("FAIL : fchown %s %d.%d, because %s", dir, uid,
82                                         gid, strerror_r(errno, buf, sizeof(buf)));
83                         close(fd);
84                         free(fullpath);
85                         return -1;
86                 }
87                 close(fd);
88         }
89
90         free(fullpath);
91
92         return 0;
93 }
94
95 static char *_get_db_path(uid_t uid)
96 {
97         const char *db_path;
98         char path[PATH_MAX];
99
100         db_path = tzplatform_getenv(TZ_SYS_DB);
101         if (db_path == NULL) {
102                 _LOGE("Failed to get TZ_SYS_DB path");
103                 return NULL;
104         }
105
106         if (uid == GLOBAL_USER || uid == ROOT_UID)
107                 return strdup(db_path);
108
109         snprintf(path, sizeof(path), "%s/user/%d", db_path, uid);
110
111         return strdup(path);
112 }
113
114 int _check_create_cert_db(void)
115 {
116         return pkgmgr_parser_initialize_cert_db();
117 }
118
119 static gid_t _get_gid(const char *name)
120 {
121         char buf[BUFSIZE];
122         struct group entry;
123         struct group *ge;
124         int ret;
125
126         ret = getgrnam_r(name, &entry, buf, sizeof(buf), &ge);
127         if (ret || ge == NULL) {
128                 _LOGE("fail to get gid of %s", name);
129                 return -1;
130         }
131
132         return entry.gr_gid;
133 }
134
135 API const char *getIconPath(uid_t uid, bool readonly)
136 {
137         const char *path = NULL;
138         uid_t uid_caller = getuid();
139         gid_t gid = ROOT_UID;
140
141         if (uid != GLOBAL_USER && uid != ROOT_UID) {
142                 _LOGD("not supported target user");
143                 return NULL;
144         }
145
146         if (readonly)
147                 path = tzplatform_mkpath(TZ_SYS_RO_ICONS, "/");
148
149         /* just allow certain users to create the icon directory if needed. */
150         if (path && (uid_caller == ROOT_UID  ||
151                 uid_caller == APPFW_UID || uid_caller == uid))
152                 _mkdir_for_user(path, uid, gid);
153
154         return path;
155 }
156
157 API char *getUserPkgParserDBPath(void)
158 {
159         return getUserPkgParserDBPathUID(_getuid());
160 }
161
162 API char *getUserPkgParserDBPathUID(uid_t uid)
163 {
164         char pkgmgr_parser_db[PATH_MAX];
165         uid_t uid_caller = getuid();
166         gid_t gid = ROOT_UID;
167         char *db_path;
168
169         db_path = _get_db_path(uid);
170         if (db_path == NULL) {
171                 _LOGE("Failed to get db path %d", uid);
172                 return NULL;
173         }
174         snprintf(pkgmgr_parser_db, sizeof(pkgmgr_parser_db),
175                         "%s/.pkgmgr_parser.db", db_path);
176         if (access(db_path, F_OK) != 0) {
177                 if (uid != GLOBAL_USER && uid != ROOT_UID) {
178                         tzplatform_set_user(uid);
179                         gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
180                         tzplatform_reset_user();
181                 }
182                 /* just allow certain users to create the dbspace directory if needed. */
183                 if (uid_caller == ROOT_UID || uid_caller == APPFW_UID)
184                         _mkdir_for_user(db_path, uid, gid);
185         }
186         free(db_path);
187
188         return strdup(pkgmgr_parser_db);
189 }
190
191 API char *getUserPkgCertDBPath(void)
192 {
193         char *db_path;
194         char pkgmgr_cert_db[PATH_MAX];
195
196         db_path = _get_db_path(GLOBAL_USER);
197         snprintf(pkgmgr_cert_db, sizeof(pkgmgr_cert_db),
198                         "%s/.pkgmgr_cert.db", db_path);
199         free(db_path);
200
201         return strdup(pkgmgr_cert_db);
202 }
203
204 API const char *getUserManifestPath(uid_t uid, bool readonly)
205 {
206         const char *path = NULL;
207         uid_t uid_caller = getuid();
208         gid_t gid = ROOT_UID;
209
210         if (uid != GLOBAL_USER && uid != ROOT_UID) {
211                 tzplatform_set_user(uid);
212                 path = tzplatform_mkpath(TZ_USER_PACKAGES, "/");
213                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
214                 tzplatform_reset_user();
215         } else {
216                 if (readonly)
217                         path = tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/");
218                 else
219                         path = tzplatform_mkpath(TZ_SYS_RW_PACKAGES, "/");
220         }
221
222         /* just allow certain users to create the icon directory if needed. */
223         if (uid_caller == ROOT_UID || uid_caller == APPFW_UID || uid_caller == uid)
224                 _mkdir_for_user(path, uid, gid);
225
226         return path;
227 }
228
229 void _save_column_int(sqlite3_stmt *stmt, int idx, int *i)
230 {
231         *i = sqlite3_column_int(stmt, idx);
232 }
233
234 inline void _save_column_str(sqlite3_stmt *stmt, int idx, char **str)
235 {
236         const char *val;
237
238         val = (const char *)sqlite3_column_text(stmt, idx);
239         if (val)
240                 *str = strdup(val);
241 }
242
243 API int pkgmgrinfo_pkginfo_set_usr_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path, uid_t uid)
244 {
245         retvm_if(pkgid == NULL, PMINFO_R_EINVAL, "pkgid is NULL\n");
246         return _pkginfo_set_usr_installed_storage(pkgid, location, external_pkg_path, uid);
247 }
248
249 API int pkgmgrinfo_pkginfo_set_installed_storage(const char *pkgid, INSTALL_LOCATION location, const char *external_pkg_path)
250 {
251         return pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid, location, external_pkg_path, _getuid());
252 }