Check map data in cache has key before access
[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 <tzplatform_config.h>
15
16 #include "pkgmgr-info.h"
17 #include "pkgmgrinfo_debug.h"
18 #include "pkgmgrinfo_private.h"
19 #include "pkgmgr_parser.h"
20 #include "pkgmgr_parser_db.h"
21 #include "manager/pkginfo_manager.h"
22
23 typedef int (*sqlite_query_callback)(void *data, int ncols,
24                 char **coltxt, char **colname);
25
26 static int _mkdir_for_user(const char *dir, uid_t uid, gid_t gid)
27 {
28         int ret;
29         char *fullpath;
30         char *subpath;
31         char buf[1024];
32         int fd;
33         struct stat sb;
34
35         fullpath = strdup(dir);
36         if (fullpath == NULL)
37                 return -1;
38         subpath = dirname(fullpath);
39         if (strlen(subpath) > 1 && strcmp(subpath, fullpath) != 0) {
40                 ret = _mkdir_for_user(fullpath, uid, gid);
41                 if (ret == -1) {
42                         free(fullpath);
43                         return ret;
44                 }
45         }
46
47         ret = mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
48         if (ret && errno != EEXIST) {
49                 free(fullpath);
50                 return ret;
51         } else if (ret && errno == EEXIST) {
52                 free(fullpath);
53                 return 0;
54         }
55
56         if (getuid() == ROOT_UID) {
57                 fd = open(dir, O_RDONLY);
58                 if (fd == -1) {
59                         _LOGE("FAIL : open %s : %s", dir,
60                                         strerror_r(errno, buf, sizeof(buf)));
61                         free(fullpath);
62                         return -1;
63                 }
64                 ret = fstat(fd, &sb);
65                 if (ret == -1) {
66                         _LOGE("FAIL : fstat %s : %s", dir,
67                                         strerror_r(errno, buf, sizeof(buf)));
68                         close(fd);
69                         free(fullpath);
70                         return -1;
71                 }
72                 if (S_ISLNK(sb.st_mode)) {
73                         _LOGE("FAIL : %s is symlink!", dir);
74                         close(fd);
75                         free(fullpath);
76                         return -1;
77                 }
78                 ret = fchown(fd, uid, gid);
79                 if (ret == -1) {
80                         _LOGE("FAIL : fchown %s %d.%d, because %s",
81                                         dir, uid, gid,
82                                         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 static gid_t _get_gid(const char *name)
115 {
116         char buf[BUFSIZE];
117         struct group entry;
118         struct group *ge;
119         int ret;
120
121         ret = getgrnam_r(name, &entry, buf, sizeof(buf), &ge);
122         if (ret || ge == NULL) {
123                 _LOGE("fail to get gid of %s", name);
124                 return -1;
125         }
126
127         return entry.gr_gid;
128 }
129
130 API const char *getIconPath(uid_t uid, bool readonly)
131 {
132         const char *path = NULL;
133         uid_t uid_caller = getuid();
134         gid_t gid = ROOT_UID;
135
136         if (uid != GLOBAL_USER && uid != ROOT_UID) {
137                 _LOGD("not supported target user");
138                 return NULL;
139         }
140
141         if (readonly)
142                 path = tzplatform_mkpath(TZ_SYS_RO_ICONS, "/");
143
144         /* just allow certain users to create the icon directory if needed. */
145         if (path && (uid_caller == ROOT_UID  ||
146                 uid_caller == APPFW_UID || uid_caller == uid))
147                 _mkdir_for_user(path, uid, gid);
148
149         return path;
150 }
151
152 API char *getUserPkgParserDBPath(void)
153 {
154         return getUserPkgParserDBPathUID(_getuid());
155 }
156
157 API char *getUserPkgParserDBPathUID(uid_t uid)
158 {
159         char pkgmgr_parser_db[PATH_MAX];
160         uid_t uid_caller = getuid();
161         gid_t gid = ROOT_UID;
162         char *db_path;
163
164         db_path = _get_db_path(uid);
165         if (db_path == NULL) {
166                 _LOGE("Failed to get db path %d", uid);
167                 return NULL;
168         }
169         snprintf(pkgmgr_parser_db, sizeof(pkgmgr_parser_db),
170                         "%s/.pkgmgr_parser.db", db_path);
171         if (access(db_path, F_OK) != 0) {
172                 if (uid != GLOBAL_USER && uid != ROOT_UID) {
173                         tzplatform_set_user(uid);
174                         gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
175                         tzplatform_reset_user();
176                 }
177                 /* just allow certain users to create the dbspace directory if needed. */
178                 if (uid_caller == ROOT_UID || uid_caller == APPFW_UID)
179                         _mkdir_for_user(db_path, uid, gid);
180         }
181         free(db_path);
182
183         return strdup(pkgmgr_parser_db);
184 }
185
186 API char *getUserPkgCertDBPath(void)
187 {
188         char *db_path;
189         char pkgmgr_cert_db[PATH_MAX];
190
191         db_path = _get_db_path(GLOBAL_USER);
192         snprintf(pkgmgr_cert_db, sizeof(pkgmgr_cert_db),
193                         "%s/.pkgmgr_cert.db", db_path);
194         free(db_path);
195
196         return strdup(pkgmgr_cert_db);
197 }
198
199 API const char *getUserManifestPath(uid_t uid, bool readonly)
200 {
201         const char *path = NULL;
202         uid_t uid_caller = getuid();
203         gid_t gid = ROOT_UID;
204
205         if (uid != GLOBAL_USER && uid != ROOT_UID) {
206                 tzplatform_set_user(uid);
207                 path = tzplatform_mkpath(TZ_USER_PACKAGES, "/");
208                 gid = _get_gid(tzplatform_getenv(TZ_SYS_USER_GROUP));
209                 tzplatform_reset_user();
210         } else {
211                 if (readonly)
212                         path = tzplatform_mkpath(TZ_SYS_RO_PACKAGES, "/");
213                 else
214                         path = tzplatform_mkpath(TZ_SYS_RW_PACKAGES, "/");
215         }
216
217         /* just allow certain users to create the icon directory if needed. */
218         if (uid_caller == ROOT_UID || uid_caller == APPFW_UID ||
219                         uid_caller == uid)
220                 _mkdir_for_user(path, uid, gid);
221
222         return path;
223 }
224
225 API int pkgmgrinfo_pkginfo_set_usr_installed_storage(const char *pkgid,
226                 INSTALL_LOCATION location, const char *external_pkg_path,
227                 uid_t uid)
228 {
229         retvm_if(pkgid == NULL, PMINFO_R_EINVAL, "pkgid is NULL\n");
230         return _pkginfo_set_usr_installed_storage(pkgid,
231                         location, external_pkg_path, uid);
232 }
233
234 API int pkgmgrinfo_pkginfo_set_installed_storage(const char *pkgid,
235                 INSTALL_LOCATION location, const char *external_pkg_path)
236 {
237         return pkgmgrinfo_pkginfo_set_usr_installed_storage(pkgid,
238                         location, external_pkg_path, _getuid());
239 }