ivi-resource-manager: add appid mapping
[profile/ivi/murphy.git] / src / plugins / ivi-resource-manager / appid.c
1 /*
2  * Copyright (c) 2012, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *  * Neither the name of Intel Corporation nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <dirent.h>
37 #include <limits.h>
38 #include <errno.h>
39
40 #include <murphy/common.h>
41
42 #include "appid.h"
43
44 #define APP_DIR   "/opt/apps"
45 #define APP_MAX   1024
46
47 typedef struct appid_map_s   appid_map_t;
48
49 struct appid_map_s {
50     const char *id;
51     const char *exe;
52 };
53
54 struct mrp_resmgr_appid_s {
55     mrp_resmgr_data_t *data;
56     mrp_htbl_t *map;
57 };
58
59 static void map_init(mrp_resmgr_appid_t *, const char *);
60 static void map_add_entry(mrp_resmgr_appid_t *, const char *, const char *);
61 static void map_free_entry(void *, void *);
62
63 static int pid2exe(const char *, char *, size_t);
64
65
66 mrp_resmgr_appid_t *mrp_resmgr_appid_create(mrp_resmgr_data_t *data)
67 {
68     mrp_resmgr_appid_t *appid;
69     mrp_htbl_config_t cfg;
70
71     cfg.nentry = APP_MAX;
72     cfg.comp = mrp_string_comp;
73     cfg.hash =  mrp_string_hash;
74     cfg.free = map_free_entry;
75     cfg.nbucket = cfg.nentry / 8;
76
77     if ((appid = mrp_allocz(sizeof(*appid)))) {
78         appid->data = data;
79         appid->map = mrp_htbl_create(&cfg);
80
81         map_init(appid, APP_DIR);
82     }
83
84     return appid;
85 }
86
87
88 void mrp_resmgr_appid_destroy(mrp_resmgr_appid_t *appid)
89 {
90     if (appid) {
91         mrp_htbl_destroy(appid->map, TRUE);
92         mrp_free(appid);
93     }
94 }
95
96 const char *mrp_resmgr_appid_find_by_pid(mrp_resmgr_appid_t *appid,
97                                          const char *pid)
98 {
99     char exe[PATH_MAX];
100     appid_map_t *entry;
101
102     if (pid2exe(pid, exe, PATH_MAX) < 0)
103         goto failed;
104
105     if (!(entry = mrp_htbl_lookup(appid->map, exe)))
106         goto failed;
107
108
109     return entry->id;
110     
111  failed:
112     return NULL;
113 }
114
115 static void map_init(mrp_resmgr_appid_t *appid, const char *dir_path)
116 {
117     DIR *dir, *bindir;
118     struct dirent *dirent, *binent;
119     struct stat stat;
120     const char *id;
121     char subdir_path[PATH_MAX];
122     char bindir_path[PATH_MAX];
123     char exe[PATH_MAX];
124
125     if (!(dir = opendir(dir_path))) {
126         mrp_log_error("iiv-resource-manager: can't open directory %s: %s",
127                       dir_path, strerror(errno));
128         return;
129     }
130
131     while ((dirent = readdir(dir))) {
132         id = dirent->d_name;
133
134         snprintf(subdir_path, sizeof(subdir_path), "%s/%s", dir_path, id);
135
136         if (lstat(subdir_path, &stat) < 0) {
137             mrp_log_error("ivi-resource-manager: can't stat %s: %s",
138                           subdir_path, strerror(errno));
139             continue;
140         }
141
142         if (!S_ISDIR(stat.st_mode) || id[0] == '.')
143             continue;
144
145         snprintf(bindir_path, sizeof(bindir_path), "%s/bin", subdir_path);
146
147         if (!(bindir = opendir(bindir_path))) {
148             mrp_log_error("ivi-resource-manager: can't open directory %s: %s",
149                           bindir_path, strerror(errno));
150             continue;
151         }
152
153         while ((binent = readdir(bindir))) {
154             snprintf(exe, sizeof(exe), "%s/%s", bindir_path, binent->d_name);
155
156             if (lstat(exe, &stat) < 0) {
157                 mrp_log_error("ivi-resource-manager: can't stat %s: %s",
158                               exe, strerror(errno));
159                 continue;
160             }
161
162             if (!S_ISREG(stat.st_mode) || !(stat.st_mode & 0111))
163                 continue;
164
165             map_add_entry(appid, id, exe);
166         }
167
168         closedir(bindir);
169
170     } /* while dirent */
171
172     closedir(dir);
173 }
174
175 static void map_add_entry(mrp_resmgr_appid_t *appid,
176                           const char *id,
177                           const char *exe)
178 {
179     appid_map_t *entry;
180
181     if (!(entry = mrp_allocz(sizeof(*entry))) ||
182         !(entry->id = mrp_strdup(id)) ||
183         !(entry->exe = mrp_strdup(exe)))
184     {
185         mrp_log_error("ivi-resource-manager: can't allocate memory");
186         return;
187     }
188
189     mrp_htbl_insert(appid->map, (void *)entry->exe, entry);
190
191     mrp_log_info("ivi-resource-manager: map exe %s => appid %s",
192                  entry->exe, entry->id);
193 }
194
195 static void map_free_entry(void *key, void *object)
196 {
197     appid_map_t *me = (appid_map_t *)object;
198
199     MRP_UNUSED(key);
200
201     free((void *)me->id);
202     free((void *)me->exe);
203     free((void *)me);
204 }
205
206 static int pid2exe(const char *pid, char *buf, size_t len)
207 {
208     FILE *f;
209     char path[PATH_MAX];
210     char *p;
211     int st = -1;
212
213     if (pid && buf && len > 0) {
214         snprintf(path, sizeof(path), "/proc/%s/cmdline", pid);
215
216         if ((f = fopen(path, "r"))) {
217             if (fgets(buf, len-1, f)) {
218                 if ((p = strchr(buf, ' ')))
219                     *p = '\0';
220                 else if ((p = strchr(buf, '\n')))
221                     *p = '\0';
222                 st = 0;
223             }
224             fclose(f);
225         }
226     }
227
228     if (st < 0)
229         mrp_log_info("ivi-resource-manager: pid2exe(%s) failed", pid);
230     else
231         mrp_log_info("ivi-resource-manager: pid %s => exe %s", pid, buf);
232
233     return st;
234 }
235
236
237 /*
238  * Local Variables:
239  * c-basic-offset: 4
240  * indent-tabs-mode: nil
241  * End:
242  *
243  */