4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
28 #include <sys/types.h>
31 #include "pkgmgr-server.h"
34 #define BACKEND_INFO_DIR "/etc/package-manager/backend"
36 static pm_queue_data *__get_head_from_pkgtype(pm_dbus_msg *item);
37 static void __update_head_from_pkgtype(pm_queue_data *data);
38 static int __entry_exist(char *backend);
39 static int __is_pkg_supported(char *pkgtype);
41 queue_info_map *start = NULL;
44 int num_of_backends = 0;
46 /*Function to check whether a particular package type
47 is supported or not. It parses the queue info map
48 to get the information.
49 It will prevent the accidental hanging of server.
51 static int __is_pkg_supported(char *pkgtype)
53 queue_info_map *ptr = NULL;
56 for(i = 0; i < entries; i++)
58 if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
68 /*tells whether a particular backend exists in the
70 * on Success it return the queue slot of the already present entry
71 * on Failure -1 is returned*/
72 static int __entry_exist(char *backend)
74 queue_info_map *ptr = NULL;
77 for(i = 0; i < entries; i++)
79 if (!strncmp(ptr->backend, backend, MAX_PKG_NAME_LEN))
80 return ptr->queue_slot;
89 /*In case of first push, it updates the queue head
90 and copies it to all duplicate entries in queue info map*/
91 static void __update_head_from_pkgtype(pm_queue_data *data)
93 queue_info_map *ptr = NULL;
97 for(i = 0; i < entries; i++)
99 if (!strncmp(ptr->pkgtype, data->msg->pkg_type, MAX_PKG_TYPE_LEN)) {
101 slot = ptr->queue_slot;
108 /*update head for each duplicate entry*/
110 for(i = 0; i < entries; i++)
112 if(ptr->queue_slot == slot && !ptr->head) {
120 /*Gets the queue head based on pkg type*/
121 static pm_queue_data *__get_head_from_pkgtype(pm_dbus_msg *item)
123 queue_info_map *ptr = NULL;
126 for(i = 0; i < entries; i++)
128 if (!strncmp(ptr->pkgtype, item->pkg_type, MAX_PKG_TYPE_LEN))
139 int _pm_queue_init(void)
141 /*Find the num of backends currently supported and initialize
142 that many queues. It is dynamically determined.*/
143 struct dirent **namelist;
144 struct stat fileinfo;
145 queue_info_map *ptr = NULL;
150 char abs_filename[MAX_PKG_NAME_LEN] = {'\0'};
151 char buf[MAX_PKG_NAME_LEN] = {'\0'};
152 n = scandir(BACKEND_INFO_DIR, &namelist, NULL, alphasort);
158 /*Find number of backends (symlinks + executables)
159 The /usr/etc/package-manager/backend dir should not conatin
160 any other file except the backends.*/
163 if(!strcmp(namelist[n]->d_name, ".") ||
164 !strcmp(namelist[n]->d_name, ".."))
166 snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
167 BACKEND_INFO_DIR, namelist[n]->d_name);
168 if (lstat(abs_filename, &fileinfo)) {
172 if (S_ISDIR(fileinfo.st_mode))
175 memset(abs_filename, 0x00, MAX_PKG_NAME_LEN);
177 /*Add entries to info map.*/
178 ptr = (queue_info_map*)calloc(c , sizeof(queue_info_map));
179 memset(ptr, '\0', c * sizeof(queue_info_map));
181 for(n = 0; n < c ; n++)
183 ptr->backend[0] = '\0';
185 ptr->queue_slot = -2;/*-1 can be error return*/
186 ptr->pkgtype[0] = '\0';
193 if(!strcmp(namelist[n]->d_name, ".") ||
194 !strcmp(namelist[n]->d_name, ".."))
196 snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
197 BACKEND_INFO_DIR, namelist[n]->d_name);
198 if (lstat(abs_filename, &fileinfo) < 0) {
199 perror(abs_filename);
202 if (S_ISDIR(fileinfo.st_mode))
205 if (S_ISLNK(fileinfo.st_mode)) {
207 ret = readlink(abs_filename, buf, MAX_PKG_NAME_LEN - 1);
216 strncpy(buf, abs_filename, MAX_PKG_NAME_LEN - 1);
218 ret = __entry_exist(buf);
220 strncpy(ptr->backend, buf, MAX_PKG_NAME_LEN - 1);
221 strncpy(ptr->pkgtype, namelist[n]->d_name, MAX_PKG_TYPE_LEN - 1);
222 ptr->queue_slot = slot;
229 strncpy(ptr->backend, buf, MAX_PKG_NAME_LEN - 1);
230 strncpy(ptr->pkgtype, namelist[n]->d_name, MAX_PKG_TYPE_LEN - 1);
231 ptr->queue_slot = ret;
237 memset(buf, 0x00, MAX_PKG_NAME_LEN);
241 num_of_backends = slot;
245 DBG("Queue Info Map");
246 DBG("Number of Backends is %d", num_of_backends);
247 DBG("Number of Entries is %d", entries);
248 DBG("Backend\tType\tSlot\tHead");
250 for(n = 0; n < entries; n++)
252 DBG("%s\t%s\t%d\t%p", ptr->backend, ptr->pkgtype, ptr->queue_slot, ptr->head);
260 pm_dbus_msg *_pm_queue_create_item(uid_t uid, const char *req_id,
261 int req_type, const char *pkg_type, const char *pkgid,
266 item = calloc(1, sizeof(pm_dbus_msg));
268 ERR("Fail to allocate memory");
273 snprintf(item->req_id, sizeof(item->req_id), "%s", req_id);
274 item->req_type = req_type;
275 snprintf(item->pkg_type, sizeof(item->pkg_type), "%s", pkg_type);
276 snprintf(item->pkgid, sizeof(item->pkgid), "%s", pkgid);
277 snprintf(item->args, sizeof(item->args), "%s", args);
282 int _pm_queue_push(pm_dbus_msg *item)
284 pm_queue_data *data = NULL;
285 pm_queue_data *cur = NULL;
286 pm_queue_data *tmp = NULL;
288 ret = __is_pkg_supported(item->pkg_type);
292 cur = __get_head_from_pkgtype(item);
296 if (!data) { /* fail to allocate mem */
297 ERR("Fail to allocate memory\n");
301 strncpy(data->msg->req_id, item->req_id, strlen(item->req_id));
302 data->msg->req_type = item->req_type;
303 data->msg->uid = item->uid;
304 strncpy(data->msg->pkg_type, item->pkg_type, strlen(item->pkg_type));
305 strncpy(data->msg->pkgid, item->pkgid, strlen(item->pkgid));
306 strncpy(data->msg->args, item->args, strlen(item->args));
313 __update_head_from_pkgtype(data);
324 /*pop request from queue slot "position" */
325 pm_dbus_msg *_pm_queue_pop(int position)
328 pm_queue_data *cur = NULL;
329 pm_queue_data *saveptr = NULL;
330 queue_info_map *ptr = NULL;
333 ret = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
335 ERR("Mem alloc error");
338 memset(ret, 0x00, sizeof(pm_dbus_msg));
340 for(i = 0; i < entries; i++)
342 if (ptr->queue_slot == position) {
349 if (!cur) { /* queue is empty */
354 strncpy(ret->req_id, cur->msg->req_id, strlen(cur->msg->req_id));
355 ret->req_type = cur->msg->req_type;
356 ret->uid = cur->msg->uid;
357 strncpy(ret->pkg_type, cur->msg->pkg_type, strlen(cur->msg->pkg_type));
358 strncpy(ret->pkgid, cur->msg->pkgid, strlen(cur->msg->pkgid));
359 strncpy(ret->args, cur->msg->args, strlen(cur->msg->args));
361 ptr->head = cur->next;
366 /*update head for each duplicate queue entry*/
368 for(i = 0; i < entries; i++)
370 if(ptr->queue_slot == position) {
378 /*populate an array of all queue heads and delete them one by one*/
379 void _pm_queue_final()
384 pm_queue_data *cur = NULL;
385 pm_queue_data *tail = NULL;
386 pm_queue_data *prev = NULL;
387 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
388 queue_info_map *ptr = NULL;
391 for(i = 0; i < num_of_backends; i++)
396 for(i = 0; i < entries; i++)
398 if (ptr->queue_slot <= slot) {
404 slot = ptr->queue_slot;
411 while(c < num_of_backends) {
412 if (!head[c]) { /* in case of head is NULL */
413 ERR("queue is NULL");
418 while (head[c]->next) {
439 /*Free the info map*/
446 pm_queue_data *_add_node()
448 pm_queue_data *newnode = NULL;
450 newnode = (pm_queue_data *) malloc(sizeof(pm_queue_data));
451 if (!newnode) { /* if NULL */
452 ERR("Mem alloc error");
455 memset(newnode, 0x00, sizeof(pm_queue_data));
457 newnode->msg = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
459 ERR("Mem alloc error");
463 memset(newnode->msg, 0x00, sizeof(pm_dbus_msg));
468 void _pm_queue_delete(pm_dbus_msg *item)
470 /* Assume that pacakge name is unique */
471 pm_queue_data *cur = NULL;
472 pm_queue_data *prev = NULL;
473 cur = __get_head_from_pkgtype(item);
477 if (!strcmp(item->pkgid, cur->msg->pkgid)) {
478 prev->next = cur->next;
489 void _save_queue_status(pm_dbus_msg *item, char *status)
491 FILE *fp_status = NULL;
493 fp_status = fopen(STATUS_FILE, "w"); /* overwrite always */
495 ERR("Can't open status file:%s", STATUS_FILE);
499 fprintf(fp_status, "%s\n", status);
500 fprintf(fp_status, "%s\n", item->pkg_type);
502 fsync(fileno(fp_status));
507 void _print_queue(int position)
509 pm_queue_data *cur = NULL;
510 queue_info_map *ptr = start;
512 for(i =0; i < entries; i++)
514 if (ptr->queue_slot == position) {