03e86eb789d60f485e49641febbbec53340ed698
[platform/core/api/package-manager.git] / src / package_manager_internal.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <sys/syscall.h>
21 #include <unistd.h>
22
23 #include <package-manager.h>
24 #include <pkgmgr-info.h>
25 #include <tzplatform_config.h>
26 #include <cynara-client.h>
27 #include <cynara-session.h>
28
29 #include "package_info.h"
30 #include "package_manager.h"
31 #include "package_manager_internal.h"
32
33 #define MAX_SMACK_LABEL_LEN 255
34 #define gettid() syscall(SYS_gettid)
35
36 typedef struct _foreach_pkg_context_ {
37         package_manager_package_info_cb callback;
38         void *user_data;
39 } foreach_pkg_context_s;
40
41 int check_privilege(privilege_type type)
42 {
43         cynara *p_cynara;
44         int fd;
45         int ret;
46         char subject_label[MAX_SMACK_LABEL_LEN + 1] = { 0 };
47         char uid[10];
48         char *session;
49         const char *privilege;
50         unsigned long pid = getpid();
51         unsigned long tid = gettid();
52
53         if (pid == tid) {
54                 fd = open("/proc/self/attr/current", O_RDONLY);
55         } else {
56                 // Check current thread smack label.
57                 char path[256] = { 0 };
58                 pid = tid;
59                 snprintf(path, sizeof(path), "/proc/%lu/attr/current", tid);
60                 fd = open(path, O_RDONLY);
61         }
62         if (fd < 0) {
63                 LOGE("open failed: %d", errno);
64                 return PACKAGE_MANAGER_ERROR_IO_ERROR;
65         }
66
67         ret = read(fd, subject_label, MAX_SMACK_LABEL_LEN);
68         if (ret < 0) {
69                 LOGE("read failed: %d", errno);
70                 close(fd);
71                 return PACKAGE_MANAGER_ERROR_IO_ERROR;
72         }
73         close(fd);
74
75         ret = cynara_initialize(&p_cynara, NULL);
76         if (ret != CYNARA_API_SUCCESS) {
77                 LOGE("init cynara failed: %d", ret);
78                 return PACKAGE_MANAGER_ERROR_IO_ERROR;
79         }
80
81         snprintf(uid, 10, "%d", getuid());
82         session = cynara_session_from_pid(pid);
83
84         switch (type) {
85         case PRIVILEGE_PACKAGE_MANAGER_INFO:
86                 privilege = "http://tizen.org/privilege/packagemanager.info";
87                 break;
88         case PRIVILEGE_PACKAGE_MANAGER_ADMIN:
89                 privilege = "http://tizen.org/privilege/packagemanager.admin";
90                 break;
91         case PRIVILEGE_PACKAGE_MANAGER_CACHE:
92                 privilege =
93                         "http://tizen.org/privilege/packagemanager.clearcache";
94                 break;
95         default:
96                 privilege = NULL;
97                 break;
98         }
99
100         ret = cynara_check(p_cynara, subject_label, session, uid, privilege);
101
102         free(session);
103         cynara_finish(p_cynara);
104
105         if (ret != CYNARA_API_ACCESS_ALLOWED) {
106                 LOGE("cynara access check failed: %d", ret);
107                 return PACKAGE_MANAGER_ERROR_PERMISSION_DENIED;
108         }
109
110         return PACKAGE_MANAGER_ERROR_NONE;
111 }
112
113 static const char *package_manager_error_to_string(package_manager_error_e
114                                                    error)
115 {
116         switch (error) {
117         case PACKAGE_MANAGER_ERROR_NONE:
118                 return "NONE";
119         case PACKAGE_MANAGER_ERROR_INVALID_PARAMETER:
120                 return "INVALID_PARAMETER";
121         case PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY:
122                 return "OUT_OF_MEMORY";
123         case PACKAGE_MANAGER_ERROR_IO_ERROR:
124                 return "IO_ERROR";
125         case PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE:
126                 return "NO_SUCH_PACKAGE";
127         case PACKAGE_MANAGER_ERROR_PERMISSION_DENIED:
128                 return "PERMISSION_DENIED";
129         case PACKAGE_MANAGER_ERROR_SYSTEM_ERROR:
130                 return "SEVERE_SYSTEM_ERROR";
131         default:
132                 return "UNKNOWN";
133         }
134 }
135
136 int package_manager_convert_internal_error(int internal_error)
137 {
138         switch (internal_error) {
139         case PKGMGR_R_ERROR:
140         case PKGMGR_R_ECOMM:
141         case PKGMGR_R_ESYSTEM:
142                 return PACKAGE_MANAGER_ERROR_SYSTEM_ERROR;
143         case PKGMGR_R_EINVAL:
144                 return PACKAGE_MANAGER_ERROR_INVALID_PARAMETER;
145         case PKGMGR_R_ETIMEOUT:
146         case PKGMGR_R_EPRIV:
147                 return PACKAGE_MANAGER_ERROR_PERMISSION_DENIED;
148         case PKGMGR_R_ENOPKG:
149                 return PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE;
150         case PKGMGR_R_ENOMEM:
151                 return PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY;
152         case PKGMGR_R_EIO:
153                 return PACKAGE_MANAGER_ERROR_IO_ERROR;
154         default:
155                 _LOGE("Unexpected error");
156                 return PACKAGE_MANAGER_ERROR_SYSTEM_ERROR;
157         }
158 }
159
160 int package_manager_error(package_manager_error_e error,
161                                  const char *function, const char *description)
162 {
163         if (description) {
164                 _LOGE("[%s] %s(0x%08x) : %s", function,
165                      package_manager_error_to_string(error), error,
166                      description);
167         } else {
168                 _LOGE("[%s] %s(0x%08x)", function,
169                      package_manager_error_to_string(error), error);
170         }
171
172         return error;
173 }
174
175 int package_info_get_package_info(const char *package, package_info_h *package_info)
176 {
177         return package_info_create(package, package_info);
178 }
179
180 static int package_info_foreach_package_info_cb(const pkgmgrinfo_pkginfo_h handle, void *user_data)
181 {
182         foreach_pkg_context_s *foreach_pkg_context = user_data;
183         package_info_h package_info = NULL;
184         bool r = false;
185         int ret;
186
187         if (handle == NULL || foreach_pkg_context == NULL) {
188                 package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
189                 return PMINFO_R_EINVAL;
190         }
191
192         ret = package_info_create_with_pkginfo(handle, &package_info);
193         if (ret != PACKAGE_MANAGER_ERROR_NONE)
194                 return package_manager_error(ret, __FUNCTION__, NULL);
195
196         r = foreach_pkg_context->callback(package_info, foreach_pkg_context->user_data);
197
198         package_info_destroy_handle(package_info);
199
200         return (r == true) ? PMINFO_R_OK : PMINFO_R_ERROR;
201 }
202
203 int package_info_foreach_package_info(package_manager_package_info_cb callback, void *user_data)
204 {
205         foreach_pkg_context_s foreach_pkg_context = {
206                 .callback = callback,
207                 .user_data = user_data,
208         };
209         int ret = 0;
210
211         if (callback == NULL)
212                 return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
213
214         ret = pkgmgrinfo_pkginfo_get_list(package_info_foreach_package_info_cb, &foreach_pkg_context);
215
216         if (ret < 0)
217                 return PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE;
218
219         return PACKAGE_MANAGER_ERROR_NONE;
220 }
221
222 int package_info_filter_foreach_package_info(pkgmgrinfo_pkginfo_filter_h handle, package_manager_package_info_cb callback, void *user_data)
223 {
224         foreach_pkg_context_s foreach_pkg_context = {
225                 .callback = callback,
226                 .user_data = user_data,
227         };
228         int ret;
229
230         if ((handle == NULL) || (callback == NULL))
231                 return package_manager_error(PACKAGE_MANAGER_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
232
233         ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle, package_info_foreach_package_info_cb, &foreach_pkg_context);
234
235         if (ret < 0)
236                 return PACKAGE_MANAGER_ERROR_IO_ERROR;
237
238         return PACKAGE_MANAGER_ERROR_NONE;
239 }