GCOV Execution Analysis for uid_utils.c
The left column is the number of times the code was executed
during the unit test suites.
Exec | Code | Line # | |
---|---|---|---|
Source:uid_utils.c | 1 | ||
Object:t/uid/uid_utils.bb | 2 | ||
/* -*- linux-c -*- | 3 | ||
* | 4 | ||
* (C) Copyright IBM Corp. 2003, 2004 | 5 | ||
* Copyright (c) 2003 by Intel Corp. | 6 | ||
* | 7 | ||
* This program is distributed in the hope that it will be useful, | 8 | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This | 10 | ||
* file and program are licensed under a BSD style license. See | 11 | ||
* the Copying file included with the OpenHPI distribution for | 12 | ||
* full licensing terms. | 13 | ||
* | 14 | ||
* Author(s): | 15 | ||
* David Judkovics < address removed > | 16 | ||
* Renier Morales < address removed > | 17 | ||
*/ | 18 | ||
19 | |||
#include <stdio.h> | 20 | ||
#include <stdlib.h> | 21 | ||
#include <glib.h> | 22 | ||
#include <fcntl.h> | 23 | ||
#include <string.h> | 24 | ||
#include <unistd.h> | 25 | ||
26 | |||
#include <SaHpi.h> | 27 | ||
#include <config.h> | 28 | ||
#include <oh_utils.h> | 29 | ||
30 | |||
static GStaticMutex oh_uid_lock = G_STATIC_MUTEX_INIT; | 31 | ||
static GHashTable *oh_ep_table; | 32 | ||
static GHashTable *oh_resource_id_table; | 33 | ||
static guint resource_id; | 34 | ||
35 | |||
36 | |||
/* use to build memory resident map table from file */ | 37 | ||
static int uid_map_from_file(void); | 38 | ||
static int build_uid_map_data(int file); | 39 | ||
40 | |||
/* used by oh_uid_remove() */ | 41 | ||
static void write_ep_xref(gpointer key, gpointer value, gpointer file); | 42 | ||
43 | |||
/* for hash table usage */ | 44 | ||
guint oh_entity_path_hash(gconstpointer key); | 45 | ||
gboolean oh_entity_path_equal(gconstpointer a, gconstpointer b); | 46 | ||
47 | |||
/* | 48 | ||
* oh_entity_path_hash: used by g_hash_table_new() | 49 | ||
* in oh_uid_initialize(). See glib library for | 50 | ||
* further details. | 51 | ||
*/ | 52 | ||
guint oh_entity_path_hash(gconstpointer key) | 53 | ||
230 | { | 54 | |
230 | const char *p = key; | 55 | |
230 | guint h = *p; | 56 | |
57 | |||
230 | int i; | 58 | |
59 | |||
230 | int entity_path_len; | 60 | |
61 | |||
230 | entity_path_len = sizeof(SaHpiEntityPathT); | 62 | |
63 | |||
230 | p += 1; | 64 | |
65 | |||
29440 | for( i=0; i<entity_path_len - 1; i++ ){ | 66 | |
/* h = (h << 5) - h + *p; */ | 67 | ||
29210 | h = (h * 131) + *p; | 68 | |
29210 | p++; | 69 | |
} | 70 | ||
71 | |||
/* don't change the 1009, its magic */ | 72 | ||
230 | return( h % 1009 ); | 73 | |
74 | |||
} | 75 | ||
76 | |||
/* | 77 | ||
* oh_entity_path_equal: used by g_hash_table_new() | 78 | ||
* in oh_uid_initialize(). See glib library for | 79 | ||
* further details. | 80 | ||
*/ | 81 | ||
gboolean oh_entity_path_equal(gconstpointer a, gconstpointer b) | 82 | ||
160 | { | 83 | |
160 | if (oh_cmp_ep(a,b)) { | 84 | |
92 | return 1; | 85 | |
} | 86 | ||
else { | 87 | ||
68 | return 0; | 88 | |
} | 89 | ||
} | 90 | ||
91 | |||
/** | 92 | ||
* oh_uid_initialize | 93 | ||
* | 94 | ||
* UID utils initialization routine | 95 | ||
* This functions must be called before any other uid_utils | 96 | ||
* are made. | 97 | ||
* | 98 | ||
* Returns: success 0, failure -1. | 99 | ||
**/ | 100 | ||
SaErrorT oh_uid_initialize(void) | 101 | ||
14 | { | 102 | |
14 | static int initialized = FALSE; | 103 | |
104 | |||
14 | int rval; | 105 | |
106 | |||
14 | uid_lock(&oh_uid_lock); | 107 | |
14 | if(!initialized) { | 108 | |
109 | |||
/* initialize hash tables */ | 110 | ||
14 | oh_ep_table = g_hash_table_new(oh_entity_path_hash, oh_entity_path_equal); | 111 | |
14 | oh_resource_id_table = g_hash_table_new(g_int_hash, g_int_equal); | 112 | |
113 | |||
14 | initialized = TRUE; | 114 | |
115 | |||
14 | resource_id = 1; | 116 | |
117 | |||
/* initialize uid map */ | 118 | ||
14 | rval = uid_map_from_file(); | 119 | |
120 | |||
0 | } else { rval = SA_ERR_HPI_ERROR; } | 121 | |
122 | |||
14 | uid_unlock(&oh_uid_lock); | 123 | |
124 | |||
14 | return(rval); | 125 | |
126 | |||
} | 127 | ||
128 | |||
/** | 129 | ||
* oh_uid_from_entity_path | 130 | ||
* @ep: value to be removed from used | 131 | ||
* | 132 | ||
* This function returns an unique value to be used as | 133 | ||
* an uid/resourceID base upon a unique entity path specified | 134 | ||
* by @ep. If the entity path already exists, the already assigned | 135 | ||
* resource id is returned. Before returning, this call updates the | 136 | ||
* uid map file saved on disk. | 137 | ||
* | 138 | ||
* Returns: positive unsigned int, failure is 0. | 139 | ||
**/ | 140 | ||
guint oh_uid_from_entity_path(SaHpiEntityPathT *ep) | 141 | ||
79 | { | 142 | |
79 | gpointer key; | 143 | |
79 | gpointer value; | 144 | |
79 | SaHpiResourceIdT ruid; | 145 | |
146 | |||
79 | EP_XREF *ep_xref; | 147 | |
148 | |||
79 | char *uid_map_file; | 149 | |
79 | int file; | 150 | |
151 | |||
79 | SaHpiEntityPathT entitypath; | 152 | |
153 | |||
79 | if (!ep) return 0; | 154 | |
155 | |||
78 | oh_init_ep(&entitypath); | 156 | |
78 | oh_concat_ep(&entitypath,ep); | 157 | |
78 | key = &entitypath; | 158 | |
159 | |||
78 | uid_lock(&oh_uid_lock); | 160 | |
/* check for presence of EP and */ | 161 | ||
/* previously assigned uid */ | 162 | ||
78 | ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); | 163 | |
78 | if (ep_xref) { | 164 | |
/*dbg("Entity Path already assigned uid. Use oh_uid_lookup().");*/ | 165 | ||
64 | uid_unlock(&oh_uid_lock); | 166 | |
64 | return ep_xref->resource_id; | 167 | |
} | 168 | ||
169 | |||
/* allocate storage for EP cross reference data structure*/ | 170 | ||
14 | ep_xref = (EP_XREF *)g_malloc0(sizeof(EP_XREF)); | 171 | |
14 | if(!ep_xref) { | 172 | |
0 | dbg("malloc failed"); | 173 | |
0 | uid_unlock(&oh_uid_lock); | 174 | |
0 | return 0; | 175 | |
} | 176 | ||
177 | |||
14 | memset(ep_xref, 0, sizeof(EP_XREF)); | 178 | |
14 | memcpy(&ep_xref->entity_path, &entitypath, sizeof(SaHpiEntityPathT)); | 179 | |
180 | |||
14 | ep_xref->resource_id = resource_id; | 181 | |
14 | resource_id++; | 182 | |
14 | ruid = ep_xref->resource_id; | 183 | |
184 | |||
14 | value = (gpointer)ep_xref; | 185 | |
186 | |||
/* entity path based key */ | 187 | ||
14 | key = (gpointer)&ep_xref->entity_path; | 188 | |
14 | g_hash_table_insert(oh_ep_table, key, value); | 189 | |
190 | |||
/* resource id based key */ | 191 | ||
14 | key = (gpointer)&ep_xref->resource_id; | 192 | |
14 | g_hash_table_insert(oh_resource_id_table, key, value); | 193 | |
194 | |||
/* save newly created ep xref (iud/resource_id) to map file */ | 195 | ||
14 | uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); | 196 | |
14 | if (uid_map_file == NULL) { | 197 | |
0 | uid_map_file = OH_DEFAULT_UID_MAP; | 198 | |
} | 199 | ||
200 | |||
14 | file = open(uid_map_file, O_WRONLY); | 201 | |
14 | if (file >= 0) { | 202 | |
14 | lseek(file, 0, SEEK_END); | 203 | |
14 | write(file,ep_xref, sizeof(EP_XREF)); | 204 | |
14 | lseek(file, 0, SEEK_SET); | 205 | |
14 | write(file, &resource_id, sizeof(resource_id)); | 206 | |
} | 207 | ||
14 | close(file); | 208 | |
209 | |||
14 | uid_unlock(&oh_uid_lock); | 210 | |
211 | |||
14 | return ruid; | 212 | |
} | 213 | ||
214 | |||
/** | 215 | ||
* oh_uid_remove | 216 | ||
* @uid: value to be removed | 217 | ||
* | 218 | ||
* This functions removes the uid/entity path | 219 | ||
* pair from use and removes the use of the uid forever. | 220 | ||
* A new uid may be requested for this entity path | 221 | ||
* in the future. oh_uid_from_entity_path() writes | 222 | ||
* the entire uid/entity path pairings to file before | 223 | ||
* returning. oh_uid_remove() deletes the pairing from file. | 224 | ||
* | 225 | ||
* Returns: success 0, failure -1. | 226 | ||
**/ | 227 | ||
gint oh_uid_remove(guint uid) | 228 | ||
5 | { | 229 | |
5 | EP_XREF *ep_xref; | 230 | |
5 | gpointer key; | 231 | |
5 | int rval; | 232 | |
233 | |||
/* check netry exist in oh_resource_id_table */ | 234 | ||
5 | key = (gpointer)&uid; | 235 | |
5 | uid_lock(&oh_uid_lock); | 236 | |
5 | ep_xref = (EP_XREF *)g_hash_table_lookup (oh_resource_id_table, key); | 237 | |
5 | if(!ep_xref) { | 238 | |
1 | dbg("error freeing oh_resource_id_table"); | 239 | |
1 | uid_unlock(&oh_uid_lock); | 240 | |
1 | return -1; | 241 | |
} | 242 | ||
243 | |||
/* check netry exist in oh_resource_id_table */ | 244 | ||
4 | key = (gpointer)&ep_xref->entity_path; | 245 | |
4 | ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); | 246 | |
4 | if(!ep_xref) { | 247 | |
0 | dbg("error freeing oh_resource_id_table"); | 248 | |
0 | uid_unlock(&oh_uid_lock); | 249 | |
0 | return -1; | 250 | |
} | 251 | ||
252 | |||
4 | g_hash_table_remove(oh_resource_id_table, &ep_xref->resource_id); | 253 | |
4 | g_hash_table_remove(oh_ep_table, &ep_xref->entity_path); | 254 | |
255 | |||
4 | free(ep_xref); | 256 | |
257 | |||
4 | uid_unlock(&oh_uid_lock); | 258 | |
259 | |||
4 | rval = oh_uid_map_to_file(); | 260 | |
261 | |||
4 | return rval; | 262 | |
} | 263 | ||
264 | |||
/** | 265 | ||
* oh_uid_lookup | 266 | ||
* @ep: pointer to entity path used to identify resourceID/uid | 267 | ||
* | 268 | ||
* Fetches resourceID/uid based on entity path in @ep. | 269 | ||
* | 270 | ||
* Returns: success returns resourceID/uid, failure is 0. | 271 | ||
**/ | 272 | ||
guint oh_uid_lookup(SaHpiEntityPathT *ep) | 273 | ||
23 | { | 274 | |
23 | EP_XREF *ep_xref; | 275 | |
23 | SaHpiEntityPathT entitypath; | 276 | |
23 | SaHpiResourceIdT ruid; | 277 | |
23 | gpointer key; | 278 | |
279 | |||
23 | if (!ep) return 0; | 280 | |
281 | |||
22 | oh_init_ep(&entitypath); | 282 | |
22 | oh_concat_ep(&entitypath, ep); | 283 | |
22 | key = &entitypath; | 284 | |
285 | |||
/* check hash table for entry in oh_ep_table */ | 286 | ||
22 | uid_lock(&oh_uid_lock); | 287 | |
22 | ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); | 288 | |
22 | if(!ep_xref) { | 289 | |
2 | dbg("error looking up EP to get uid"); | 290 | |
2 | uid_unlock(&oh_uid_lock); | 291 | |
2 | return 0; | 292 | |
} | 293 | ||
294 | |||
20 | ruid = ep_xref->resource_id; | 295 | |
20 | uid_unlock(&oh_uid_lock); | 296 | |
297 | |||
20 | return ruid; | 298 | |
} | 299 | ||
300 | |||
/** | 301 | ||
* oh_entity_path_lookup | 302 | ||
* @id: pointer to resource_id/uid identifying entity path | 303 | ||
* @ep: pointer to memory to fill in with entity path | 304 | ||
* | 305 | ||
* Fetches entity path based upon resource id, @id. | 306 | ||
* | 307 | ||
* Returns: success 0, failed -1. | 308 | ||
**/ | 309 | ||
gint oh_entity_path_lookup(guint *id, SaHpiEntityPathT *ep) | 310 | ||
16 | { | 311 | |
16 | EP_XREF *ep_xref; | 312 | |
16 | gpointer key = id; | 313 | |
314 | |||
16 | if (!id || !ep) return -1; | 315 | |
316 | |||
/* check hash table for entry in oh_ep_table */ | 317 | ||
13 | uid_lock(&oh_uid_lock); | 318 | |
13 | ep_xref = (EP_XREF *)g_hash_table_lookup (oh_resource_id_table, key); | 319 | |
13 | if(!ep_xref) { | 320 | |
2 | dbg("error looking up EP to get uid"); | 321 | |
2 | uid_unlock(&oh_uid_lock); | 322 | |
2 | return -1 ; | 323 | |
} | 324 | ||
325 | |||
11 | memcpy(ep, &ep_xref->entity_path, sizeof(SaHpiEntityPathT)); | 326 | |
327 | |||
11 | uid_unlock(&oh_uid_lock); | 328 | |
329 | |||
11 | return 0; | 330 | |
} | 331 | ||
332 | |||
/** | 333 | ||
* oh_uid_map_to_file: saves current uid and entity path mappings | 334 | ||
* to file, first element in file is 4 bytes for resource id, | 335 | ||
* then repeat EP_XREF structures holding uid and entity path pairings | 336 | ||
* | 337 | ||
* Return value: success 0, failed -1. | 338 | ||
**/ | 339 | ||
gint oh_uid_map_to_file(void) | 340 | ||
4 | { | 341 | |
4 | char *uid_map_file; | 342 | |
4 | int file; | 343 | |
344 | |||
4 | uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); | 345 | |
346 | |||
4 | if (uid_map_file == NULL) { | 347 | |
0 | uid_map_file = OH_DEFAULT_UID_MAP; | 348 | |
} | 349 | ||
350 | |||
4 | uid_lock(&oh_uid_lock); | 351 | |
352 | |||
4 | file = open(uid_map_file, O_WRONLY|O_CREAT|O_TRUNC); | 353 | |
4 | if(file < 0) { | 354 | |
0 | dbg("Configuration file '%s' could not be opened", uid_map_file); | 355 | |
0 | uid_unlock(&oh_uid_lock); | 356 | |
0 | return -1; | 357 | |
} | 358 | ||
359 | |||
/* write resource id */ | 360 | ||
4 | write(file, (void *)&resource_id, sizeof(resource_id)); | 361 | |
362 | |||
/* write all EP_XREF data records */ | 363 | ||
4 | g_hash_table_foreach(oh_resource_id_table, write_ep_xref, &file); | 364 | |
365 | |||
4 | if(close(file) != 0) { | 366 | |
0 | dbg("Couldn't close file '%s'.", uid_map_file); | 367 | |
0 | uid_unlock(&oh_uid_lock); | 368 | |
0 | return -1; | 369 | |
} | 370 | ||
371 | |||
4 | uid_unlock(&oh_uid_lock); | 372 | |
373 | |||
4 | return 0; | 374 | |
} | 375 | ||
376 | |||
377 | |||
/* | 378 | ||
* write_ep_xref: called by g_hash_table_foreach(), for each | 379 | ||
* hash table entry see glib manual for further details | 380 | ||
* | 381 | ||
* Return value: None (void). | 382 | ||
*/ | 383 | ||
static void write_ep_xref(gpointer key, gpointer value, gpointer file) | 384 | ||
34 | { | 385 | |
34 | write(*(int *)file, value, sizeof(EP_XREF)); | 386 | |
} | 387 | ||
388 | |||
389 | |||
/* | 390 | ||
* uid_map_from_file: called from oh_uid_initialize() during intialization | 391 | ||
* This function, if a uid map file exists, reads the current value for | 392 | ||
* uid and intializes the memory resident uid map file from file. | 393 | ||
* | 394 | ||
* Return value: success 0, error -1. | 395 | ||
*/ | 396 | ||
static gint uid_map_from_file() | 397 | ||
14 | { | 398 | |
14 | char *uid_map_file; | 399 | |
14 | int file; | 400 | |
14 | int rval; | 401 | |
402 | |||
/* initialize uid map file */ | 403 | ||
14 | uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); | 404 | |
14 | if (uid_map_file == NULL) { | 405 | |
0 | uid_map_file = OH_DEFAULT_UID_MAP; | 406 | |
} | 407 | ||
14 | file = open(uid_map_file, O_RDONLY); | 408 | |
14 | if(file < 0) { | 409 | |
/* create map file with resource id initial value */ | 410 | ||
1 | dbg("Configuration file '%s' does not exist, initializing", uid_map_file); | 411 | |
1 | file = open(uid_map_file, | 412 | |
O_RDWR | O_CREAT | O_TRUNC, | 413 | ||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); | 414 | ||
1 | if(file < 0) { | 415 | |
0 | dbg("Could not initialize uid map file, %s", uid_map_file ); | 416 | |
0 | return -1; | 417 | |
} | 418 | ||
/* write initial uid value */ | 419 | ||
1 | if( write(file,(void *)&resource_id, sizeof(resource_id)) < 0 ) { | 420 | |
0 | dbg("failed to write uid, on uid map file initialization"); | 421 | |
0 | close(file); | 422 | |
0 | return -1; | 423 | |
} | 424 | ||
1 | if(close(file) != 0) { | 425 | |
0 | dbg("Couldn't close file '%s'.during uid map file initialization", uid_map_file); | 426 | |
0 | return -1; | 427 | |
} | 428 | ||
/* return from successful initialization, from newly created uid map file */ | 429 | ||
1 | return 0; | 430 | |
} | 431 | ||
432 | |||
/* read uid/resouce_id highest count from uid map file */ | 433 | ||
13 | if (read(file,&resource_id, sizeof(resource_id)) != sizeof(resource_id)) { | 434 | |
0 | dbg("error setting uid from existing uid map file"); | 435 | |
0 | return -1; | 436 | |
} | 437 | ||
438 | |||
13 | rval = build_uid_map_data(file); | 439 | |
13 | close(file); | 440 | |
441 | |||
13 | if (rval < 0) | 442 | |
0 | return -1; | 443 | |
444 | |||
/* return from successful initialization from existing uid map file */ | 445 | ||
13 | return 0; | 446 | |
} | 447 | ||
448 | |||
/* | 449 | ||
* build_uid_map_data: used by uid_map_from_file(), recursively | 450 | ||
* reads map file and builds two hash tables and EP_XREF data | 451 | ||
* structures | 452 | ||
* | 453 | ||
* @file: key into a GHashTable | 454 | ||
* | 455 | ||
* Return value: success 0, error -1. | 456 | ||
*/ | 457 | ||
static gint build_uid_map_data(int file) | 458 | ||
13 | { | 459 | |
13 | int rval; | 460 | |
13 | EP_XREF *ep_xref; | 461 | |
13 | EP_XREF ep_xref1; | 462 | |
13 | gpointer value; | 463 | |
13 | gpointer key; | 464 | |
465 | |||
13 | rval = read(file, &ep_xref1, sizeof(EP_XREF)); | 466 | |
467 | |||
121 | while ( (rval != EOF) && (rval == sizeof(EP_XREF)) ) { | 468 | |
469 | |||
/* copy read record from ep_xref1 to malloc'd ep_xref */ | 470 | ||
108 | ep_xref = (EP_XREF *)g_malloc0(sizeof(EP_XREF)); | 471 | |
108 | if (!ep_xref) | 472 | |
0 | return -1; | 473 | |
108 | memcpy(ep_xref, &ep_xref1, sizeof(EP_XREF)); | 474 | |
475 | |||
108 | value = (gpointer)ep_xref; | 476 | |
477 | |||
/* entity path based key */ | 478 | ||
108 | key = (gpointer)&ep_xref->entity_path; | 479 | |
108 | g_hash_table_insert(oh_ep_table, key, value); | 480 | |
481 | |||
/* resource id based key */ | 482 | ||
108 | key = (gpointer)&ep_xref->resource_id; | 483 | |
108 | g_hash_table_insert(oh_resource_id_table, key, value); | 484 | |
485 | |||
108 | rval = read(file, &ep_xref1, sizeof(EP_XREF)); | 486 | |
} | 487 | ||
488 | |||
/* TODO thought EOF would return -1, its not so check other way */ | 489 | ||
/* if (rval != EOF), rval of 0 seems to be EOF */ | 490 | ||
13 | if ( (rval > 0) && (rval < sizeof(EP_XREF)) ) { | 491 | |
0 | dbg("error building ep xref from map file"); | 492 | |
0 | return -1; | 493 | |
} | 494 | ||
13 | return 0; | 495 | |
} | 496 |