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))
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 int _pm_queue_push(pm_dbus_msg *item)
262 pm_queue_data *data = NULL;
263 pm_queue_data *cur = NULL;
264 pm_queue_data *tmp = NULL;
266 ret = __is_pkg_supported(item->pkg_type);
270 cur = __get_head_from_pkgtype(item);
274 if (!data) { /* fail to allocate mem */
275 ERR("Fail to allocate memory\n");
279 strncpy(data->msg->req_id, item->req_id, strlen(item->req_id));
280 data->msg->req_type = item->req_type;
281 data->msg->uid = item->uid;
282 strncpy(data->msg->pkg_type, item->pkg_type, strlen(item->pkg_type));
283 strncpy(data->msg->pkgid, item->pkgid, strlen(item->pkgid));
284 strncpy(data->msg->args, item->args, strlen(item->args));
291 __update_head_from_pkgtype(data);
302 /*pop request from queue slot "position" */
303 pm_dbus_msg *_pm_queue_pop(int position)
306 pm_queue_data *cur = NULL;
307 pm_queue_data *saveptr = NULL;
308 queue_info_map *ptr = NULL;
311 ret = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
313 ERR("Mem alloc error");
316 memset(ret, 0x00, sizeof(pm_dbus_msg));
318 for(i = 0; i < entries; i++)
320 if (ptr->queue_slot == position) {
327 if (!cur) { /* queue is empty */
332 strncpy(ret->req_id, cur->msg->req_id, strlen(cur->msg->req_id));
333 ret->req_type = cur->msg->req_type;
334 ret->uid = cur->msg->uid;
335 strncpy(ret->pkg_type, cur->msg->pkg_type, strlen(cur->msg->pkg_type));
336 strncpy(ret->pkgid, cur->msg->pkgid, strlen(cur->msg->pkgid));
337 strncpy(ret->args, cur->msg->args, strlen(cur->msg->args));
339 ptr->head = cur->next;
344 /*update head for each duplicate queue entry*/
346 for(i = 0; i < entries; i++)
348 if(ptr->queue_slot == position) {
356 /*populate an array of all queue heads and delete them one by one*/
357 void _pm_queue_final()
362 pm_queue_data *cur = NULL;
363 pm_queue_data *tail = NULL;
364 pm_queue_data *prev = NULL;
365 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
366 queue_info_map *ptr = NULL;
369 for(i = 0; i < num_of_backends; i++)
374 for(i = 0; i < entries; i++)
376 if (ptr->queue_slot <= slot) {
382 slot = ptr->queue_slot;
389 while(c < num_of_backends) {
390 if (!head[c]) { /* in case of head is NULL */
391 ERR("queue is NULL");
396 while (head[c]->next) {
417 /*Free the info map*/
424 pm_queue_data *_add_node()
426 pm_queue_data *newnode = NULL;
428 newnode = (pm_queue_data *) malloc(sizeof(pm_queue_data));
429 if (!newnode) { /* if NULL */
430 ERR("Mem alloc error");
433 memset(newnode, 0x00, sizeof(pm_queue_data));
435 newnode->msg = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
437 ERR("Mem alloc error");
441 memset(newnode->msg, 0x00, sizeof(pm_dbus_msg));
446 void _pm_queue_delete(pm_dbus_msg *item)
448 /* Assume that pacakge name is unique */
449 pm_queue_data *cur = NULL;
450 pm_queue_data *prev = NULL;
451 cur = __get_head_from_pkgtype(item);
455 if (!strcmp(item->pkgid, cur->msg->pkgid)) {
456 prev->next = cur->next;
467 void _save_queue_status(pm_dbus_msg *item, char *status)
469 FILE *fp_status = NULL;
471 fp_status = fopen(STATUS_FILE, "w"); /* overwrite always */
473 ERR("Can't open status file:%s", STATUS_FILE);
477 fprintf(fp_status, "%s\n", status);
478 fprintf(fp_status, "%s\n", item->pkg_type);
480 fsync(fileno(fp_status));
485 void _print_queue(int position)
487 pm_queue_data *cur = NULL;
488 queue_info_map *ptr = start;
490 for(i =0; i < entries; i++)
492 if (ptr->queue_slot == position) {