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>
32 #include "pkgmgr-server.h"
36 #define BACKEND_DIR "/etc/package-manager/backend"
39 static pm_queue_data *__get_head_from_pkgtype(const char *pkg_type);
40 static void __update_head_from_pkgtype(pm_queue_data *data);
41 static int __entry_exist(char *backend);
42 static int __is_pkg_supported(const char *pkgtype);
44 queue_info_map *start = NULL;
47 int num_of_backends = 0;
49 /*Function to check whether a particular package type
50 is supported or not. It parses the queue info map
51 to get the information.
52 It will prevent the accidental hanging of server.
54 static int __is_pkg_supported(const char *pkgtype)
56 queue_info_map *ptr = NULL;
59 for(i = 0; i < entries; i++)
61 if (!strncmp(ptr->pkgtype, pkgtype, MAX_PKG_TYPE_LEN))
71 /*tells whether a particular backend exists in the
73 * on Success it return the queue slot of the already present entry
74 * on Failure -1 is returned*/
75 static int __entry_exist(char *backend)
77 queue_info_map *ptr = NULL;
80 for(i = 0; i < entries; i++)
82 if (!strncmp(ptr->backend, backend, MAX_PKG_NAME_LEN))
83 return ptr->queue_slot;
92 /*In case of first push, it updates the queue head
93 and copies it to all duplicate entries in queue info map*/
94 static void __update_head_from_pkgtype(pm_queue_data *data)
96 queue_info_map *ptr = NULL;
100 for(i = 0; i < entries; i++)
102 if (!strncmp(ptr->pkgtype, data->msg->pkg_type, MAX_PKG_TYPE_LEN)) {
104 slot = ptr->queue_slot;
111 /*update head for each duplicate entry*/
113 for(i = 0; i < entries; i++)
115 if(ptr->queue_slot == slot && !ptr->head) {
123 /*Gets the queue head based on pkg type*/
124 static pm_queue_data *__get_head_from_pkgtype(const char *pkg_type)
126 queue_info_map *ptr = NULL;
129 for(i = 0; i < entries; i++)
131 if (!strncmp(ptr->pkgtype, pkg_type, MAX_PKG_TYPE_LEN))
142 int _pm_queue_init(void)
144 /*Find the num of backends currently supported and initialize
145 that many queues. It is dynamically determined.*/
146 struct dirent **namelist;
147 struct stat fileinfo;
148 queue_info_map *ptr = NULL;
153 char abs_filename[MAX_PKG_NAME_LEN] = {'\0'};
154 char buf[MAX_PKG_NAME_LEN] = {'\0'};
155 n = scandir(BACKEND_DIR, &namelist, NULL, alphasort);
161 /*Find number of backends (symlinks + executables)
162 The backend dir should not conatin any other file except the backends.*/
165 if(!strcmp(namelist[n]->d_name, ".") ||
166 !strcmp(namelist[n]->d_name, ".."))
168 snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
169 BACKEND_DIR, namelist[n]->d_name);
170 if (lstat(abs_filename, &fileinfo)) {
174 if (S_ISDIR(fileinfo.st_mode))
177 memset(abs_filename, 0x00, MAX_PKG_NAME_LEN);
179 /*Add entries to info map.*/
180 ptr = (queue_info_map*)calloc(c , sizeof(queue_info_map));
181 memset(ptr, '\0', c * sizeof(queue_info_map));
183 for(n = 0; n < c ; n++)
185 ptr->backend[0] = '\0';
187 ptr->queue_slot = -2;/*-1 can be error return*/
188 ptr->pkgtype[0] = '\0';
195 if(!strcmp(namelist[n]->d_name, ".") ||
196 !strcmp(namelist[n]->d_name, ".."))
198 snprintf(abs_filename, MAX_PKG_NAME_LEN, "%s/%s",
199 BACKEND_DIR, namelist[n]->d_name);
200 if (lstat(abs_filename, &fileinfo) < 0) {
201 perror(abs_filename);
204 if (S_ISDIR(fileinfo.st_mode))
207 if (S_ISLNK(fileinfo.st_mode)) {
209 ret = readlink(abs_filename, buf, MAX_PKG_NAME_LEN - 1);
218 snprintf(buf, sizeof(buf), "%s", abs_filename);
220 ret = __entry_exist(buf);
222 snprintf(ptr->backend, sizeof(ptr->backend), "%s", buf);
223 snprintf(ptr->pkgtype, sizeof(ptr->pkgtype), "%s", namelist[n]->d_name);
224 ptr->queue_slot = slot;
231 snprintf(ptr->backend, sizeof(ptr->backend), "%s", buf);
232 snprintf(ptr->pkgtype, sizeof(ptr->pkgtype), "%s", namelist[n]->d_name);
233 ptr->queue_slot = ret;
239 memset(buf, 0x00, MAX_PKG_NAME_LEN);
243 num_of_backends = slot;
247 DBG("Queue Info Map");
248 DBG("Number of Backends is %d", num_of_backends);
249 DBG("Number of Entries is %d", entries);
250 DBG("Backend\tType\tSlot\tHead");
252 for(n = 0; n < entries; n++)
254 DBG("%s\t%s\t%d\t%p", ptr->backend, ptr->pkgtype, ptr->queue_slot, ptr->head);
262 static void __convert_to_lower_case(char *dst, const char *src)
266 for (i = 0; src[i] != '\0'; i++)
267 dst[i] = tolower(src[i]);
271 int _pm_queue_push(uid_t uid, const char *req_id, int req_type,
272 const char *queue_type, const char *pkgid, const char *args)
274 pm_queue_data *data = NULL;
275 pm_queue_data *cur = NULL;
276 pm_queue_data *tmp = NULL;
277 char type[MAX_PKG_NAME_LEN];
280 __convert_to_lower_case(type, queue_type);
282 ret = __is_pkg_supported(type);
286 cur = __get_head_from_pkgtype(type);
289 /* TODO: use glist */
291 if (!data) { /* fail to allocate mem */
292 ERR("Fail to allocate memory\n");
296 snprintf(data->msg->req_id, sizeof(data->msg->req_id), "%s", req_id);
297 data->msg->req_type = req_type;
298 data->msg->uid = uid;
299 snprintf(data->msg->pkg_type, sizeof(data->msg->pkg_type), "%s", type);
300 snprintf(data->msg->pkgid, sizeof(data->msg->pkgid), "%s", pkgid);
301 snprintf(data->msg->args, sizeof(data->msg->args), "%s", args);
308 __update_head_from_pkgtype(data);
319 /*pop request from queue slot "position" */
320 pm_dbus_msg *_pm_queue_pop(int position)
323 pm_queue_data *cur = NULL;
324 pm_queue_data *saveptr = NULL;
325 queue_info_map *ptr = NULL;
328 ret = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
330 ERR("Mem alloc error");
333 memset(ret, 0x00, sizeof(pm_dbus_msg));
335 for(i = 0; i < entries; i++)
337 if (ptr->queue_slot == position) {
344 if (!cur) { /* queue is empty */
349 snprintf(ret->req_id, sizeof(ret->req_id), "%s", cur->msg->req_id);
350 ret->req_type = cur->msg->req_type;
351 ret->uid = cur->msg->uid;
352 snprintf(ret->pkg_type, sizeof(ret->pkg_type), "%s", cur->msg->pkg_type);
353 snprintf(ret->pkgid, sizeof(ret->pkgid), "%s", cur->msg->pkgid);
354 snprintf(ret->args, sizeof(ret->args), "%s", cur->msg->args);
356 ptr->head = cur->next;
361 /*update head for each duplicate queue entry*/
363 for(i = 0; i < entries; i++)
365 if(ptr->queue_slot == position) {
373 /*populate an array of all queue heads and delete them one by one*/
374 void _pm_queue_final()
379 pm_queue_data *cur = NULL;
380 pm_queue_data *tail = NULL;
381 pm_queue_data *prev = NULL;
382 pm_queue_data *head[MAX_QUEUE_NUM] = {NULL,};
383 queue_info_map *ptr = NULL;
386 for(i = 0; i < num_of_backends; i++)
391 for(i = 0; i < entries; i++)
393 if (ptr->queue_slot <= slot) {
399 slot = ptr->queue_slot;
406 while(c < num_of_backends) {
407 if (!head[c]) { /* in case of head is NULL */
408 ERR("queue is NULL");
413 while (head[c]->next) {
434 /*Free the info map*/
441 pm_queue_data *_add_node()
443 pm_queue_data *newnode = NULL;
445 newnode = (pm_queue_data *) malloc(sizeof(pm_queue_data));
446 if (!newnode) { /* if NULL */
447 ERR("Mem alloc error");
450 memset(newnode, 0x00, sizeof(pm_queue_data));
452 newnode->msg = (pm_dbus_msg *) malloc(sizeof(pm_dbus_msg));
454 ERR("Mem alloc error");
458 memset(newnode->msg, 0x00, sizeof(pm_dbus_msg));
463 void _pm_queue_delete(pm_dbus_msg *item)
465 /* Assume that pacakge name is unique */
466 pm_queue_data *cur = NULL;
467 pm_queue_data *prev = NULL;
468 cur = __get_head_from_pkgtype(item->pkg_type);
472 if (!strcmp(item->pkgid, cur->msg->pkgid)) {
473 prev->next = cur->next;
484 void _save_queue_status(pm_dbus_msg *item, char *status)
486 FILE *fp_status = NULL;
488 fp_status = fopen(STATUS_FILE, "w"); /* overwrite always */
490 ERR("Can't open status file:%s", STATUS_FILE);
494 fprintf(fp_status, "%s\n", status);
495 fprintf(fp_status, "%s\n", item->pkg_type);
497 fsync(fileno(fp_status));
502 void _print_queue(int position)
504 pm_queue_data *cur = NULL;
505 queue_info_map *ptr = start;
507 for(i =0; i < entries; i++)
509 if (ptr->queue_slot == position) {