📄 uid_utils.c
字号:
/* -*- linux-c -*- * * (C) Copyright IBM Corp. 2003, 2004 * Copyright (c) 2003 by Intel Corp. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This * file and program are licensed under a BSD style license. See * the Copying file included with the OpenHPI distribution for * full licensing terms. * * Author(s): * David Judkovics <djudkovi@us.ibm.com> * Renier Morales <renierm@users.sf.net> */ #include <stdio.h>#include <stdlib.h>#include <glib.h>#include <fcntl.h>#include <string.h>#include <unistd.h>#include <SaHpi.h>#include <config.h>#include <oh_utils.h>static GStaticMutex oh_uid_lock = G_STATIC_MUTEX_INIT;static GHashTable *oh_ep_table;static GHashTable *oh_resource_id_table;static guint resource_id;/* use to build memory resident map table from file */static int uid_map_from_file(void);static int build_uid_map_data(int file);/* used by oh_uid_remove() */static void write_ep_xref(gpointer key, gpointer value, gpointer file);/* for hash table usage */guint oh_entity_path_hash(gconstpointer key);gboolean oh_entity_path_equal(gconstpointer a, gconstpointer b);/* * oh_entity_path_hash: used by g_hash_table_new() * in oh_uid_initialize(). See glib library for * further details. */guint oh_entity_path_hash(gconstpointer key){ const char *p = key; guint h = *p; int i; int entity_path_len; entity_path_len = sizeof(SaHpiEntityPathT); p += 1; for( i=0; i<entity_path_len - 1; i++ ){/* h = (h << 5) - h + *p; */ h = (h * 131) + *p; p++; } /* don't change the 1009, its magic */ return( h % 1009 );}/* * oh_entity_path_equal: used by g_hash_table_new() * in oh_uid_initialize(). See glib library for * further details. */gboolean oh_entity_path_equal(gconstpointer a, gconstpointer b){ if (!ep_cmp(a,b)) { return 1; } else { return 0; }}/** * oh_uid_initialize * * UID utils initialization routine * This functions must be called before any other uid_utils * are made. * * Returns: success 0, failure -1. **/SaErrorT oh_uid_initialize(void) { static int initialized = FALSE; int rval; g_static_mutex_lock(&oh_uid_lock); if(!initialized) { /* initialize hash tables */ oh_ep_table = g_hash_table_new(oh_entity_path_hash, oh_entity_path_equal); oh_resource_id_table = g_hash_table_new(g_int_hash, g_int_equal); initialized = TRUE; resource_id = 1; /* initialize uid map */ rval = uid_map_from_file(); } else { rval = SA_ERR_HPI_ERROR; } g_static_mutex_unlock(&oh_uid_lock); return(rval);}/** * oh_uid_from_entity_path * @ep: value to be removed from used * * This function returns an unique value to be used as * an uid/resourceID base upon a unique entity path specified * by @ep. If the entity path already exists, the already assigned * resource id is returned. Before returning, this call updates the * uid map file saved on disk. * * Returns: positive unsigned int, failure is 0. **/guint oh_uid_from_entity_path(SaHpiEntityPathT *ep) { gpointer key; gpointer value; SaHpiResourceIdT ruid; EP_XREF *ep_xref; char *uid_map_file; int file; SaHpiEntityPathT entitypath; if (!ep) return 0; ep_init(&entitypath); ep_concat(&entitypath,ep); key = &entitypath; g_static_mutex_lock(&oh_uid_lock); /* check for presence of EP and */ /* previously assigned uid */ ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); if (ep_xref) { /*dbg("Entity Path already assigned uid. Use oh_uid_lookup().");*/ g_static_mutex_unlock(&oh_uid_lock); return ep_xref->resource_id; } /* allocate storage for EP cross reference data structure*/ ep_xref = (EP_XREF *)g_malloc0(sizeof(EP_XREF)); if(!ep_xref) { dbg("malloc failed"); g_static_mutex_unlock(&oh_uid_lock); return 0; } memset(ep_xref, 0, sizeof(EP_XREF)); memcpy(&ep_xref->entity_path, &entitypath, sizeof(SaHpiEntityPathT)); ep_xref->resource_id = resource_id; resource_id++; ruid = ep_xref->resource_id; value = (gpointer)ep_xref; /* entity path based key */ key = (gpointer)&ep_xref->entity_path; g_hash_table_insert(oh_ep_table, key, value); /* resource id based key */ key = (gpointer)&ep_xref->resource_id; g_hash_table_insert(oh_resource_id_table, key, value); /* save newly created ep xref (iud/resource_id) to map file */ uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); if (uid_map_file == NULL) { uid_map_file = OH_DEFAULT_UID_MAP; } file = open(uid_map_file, O_WRONLY); if (file >= 0) { lseek(file, 0, SEEK_END); write(file,ep_xref, sizeof(EP_XREF)); lseek(file, 0, SEEK_SET); write(file, &resource_id, sizeof(resource_id)); } close(file); g_static_mutex_unlock(&oh_uid_lock); return ruid;} /** * oh_uid_remove * @uid: value to be removed * * This functions removes the uid/entity path * pair from use and removes the use of the uid forever. * A new uid may be requested for this entity path * in the future. oh_uid_from_entity_path() writes * the entire uid/entity path pairings to file before * returning. oh_uid_remove() deletes the pairing from file. * * Returns: success 0, failure -1. **/gint oh_uid_remove(guint uid){ EP_XREF *ep_xref; gpointer key; int rval; /* check netry exist in oh_resource_id_table */ key = (gpointer)&uid; g_static_mutex_lock(&oh_uid_lock); ep_xref = (EP_XREF *)g_hash_table_lookup (oh_resource_id_table, key); if(!ep_xref) { dbg("error freeing oh_resource_id_table"); g_static_mutex_unlock(&oh_uid_lock); return -1; } /* check netry exist in oh_resource_id_table */ key = (gpointer)&ep_xref->entity_path; ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); if(!ep_xref) { dbg("error freeing oh_resource_id_table"); g_static_mutex_unlock(&oh_uid_lock); return -1; } g_hash_table_remove(oh_resource_id_table, &ep_xref->resource_id); g_hash_table_remove(oh_ep_table, &ep_xref->entity_path); free(ep_xref); g_static_mutex_unlock(&oh_uid_lock); rval = oh_uid_map_to_file(); return rval;}/** * oh_uid_lookup * @ep: pointer to entity path used to identify resourceID/uid * * Fetches resourceID/uid based on entity path in @ep. * * Returns: success returns resourceID/uid, failure is 0. **/guint oh_uid_lookup(SaHpiEntityPathT *ep){ EP_XREF *ep_xref; SaHpiEntityPathT entitypath; SaHpiResourceIdT ruid; gpointer key; if (!ep) return 0; ep_init(&entitypath); ep_concat(&entitypath, ep); key = &entitypath; /* check hash table for entry in oh_ep_table */ g_static_mutex_lock(&oh_uid_lock); ep_xref = (EP_XREF *)g_hash_table_lookup (oh_ep_table, key); if(!ep_xref) { dbg("error looking up EP to get uid"); g_static_mutex_unlock(&oh_uid_lock); return 0; } ruid = ep_xref->resource_id; g_static_mutex_unlock(&oh_uid_lock); return ruid;}/** * oh_entity_path_lookup * @id: pointer to resource_id/uid identifying entity path * @ep: pointer to memory to fill in with entity path * * Fetches entity path based upon resource id, @id. * * Returns: success 0, failed -1. **/gint oh_entity_path_lookup(guint *id, SaHpiEntityPathT *ep){ EP_XREF *ep_xref; gpointer key = id; if (!id || !ep) return -1; /* check hash table for entry in oh_ep_table */ g_static_mutex_lock(&oh_uid_lock); ep_xref = (EP_XREF *)g_hash_table_lookup (oh_resource_id_table, key); if(!ep_xref) { dbg("error looking up EP to get uid"); g_static_mutex_unlock(&oh_uid_lock); return -1 ; } memcpy(ep, &ep_xref->entity_path, sizeof(SaHpiEntityPathT)); g_static_mutex_unlock(&oh_uid_lock); return 0;} /** * oh_uid_map_to_file: saves current uid and entity path mappings * to file, first element in file is 4 bytes for resource id, * then repeat EP_XREF structures holding uid and entity path pairings * * Return value: success 0, failed -1. **/gint oh_uid_map_to_file(void){ char *uid_map_file; int file; uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); if (uid_map_file == NULL) { uid_map_file = OH_DEFAULT_UID_MAP; } g_static_mutex_lock(&oh_uid_lock); file = open(uid_map_file, O_WRONLY|O_CREAT|O_TRUNC); if(file < 0) { dbg("Configuration file '%s' could not be opened", uid_map_file); g_static_mutex_unlock(&oh_uid_lock); return -1; } /* write resource id */ write(file, (void *)&resource_id, sizeof(resource_id)); /* write all EP_XREF data records */ g_hash_table_foreach(oh_resource_id_table, write_ep_xref, &file); if(close(file) != 0) { dbg("Couldn't close file '%s'.", uid_map_file); g_static_mutex_unlock(&oh_uid_lock); return -1; } g_static_mutex_unlock(&oh_uid_lock); return 0;}/* * write_ep_xref: called by g_hash_table_foreach(), for each * hash table entry see glib manual for further details * * Return value: None (void). */static void write_ep_xref(gpointer key, gpointer value, gpointer file){ write(*(int *)file, value, sizeof(EP_XREF));}/* * uid_map_from_file: called from oh_uid_initialize() during intialization * This function, if a uid map file exists, reads the current value for * uid and intializes the memory resident uid map file from file. * * Return value: success 0, error -1. */static gint uid_map_from_file(){ char *uid_map_file; int file; int rval; /* initialize uid map file */ uid_map_file = (char *)getenv("OPENHPI_UID_MAP"); if (uid_map_file == NULL) { uid_map_file = OH_DEFAULT_UID_MAP; } file = open(uid_map_file, O_RDONLY); if(file < 0) { /* create map file with resource id initial value */ dbg("Configuration file '%s' does not exist, initializing", uid_map_file); file = open(uid_map_file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); if(file < 0) { dbg("Could not initialize uid map file, %s", uid_map_file ); return -1; } /* write initial uid value */ if( write(file,(void *)&resource_id, sizeof(resource_id)) < 0 ) { dbg("failed to write uid, on uid map file initialization"); close(file); return -1; } if(close(file) != 0) { dbg("Couldn't close file '%s'.during uid map file initialization", uid_map_file); return -1; } /* return from successful initialization, from newly created uid map file */ return 0; } /* read uid/resouce_id highest count from uid map file */ if (read(file,&resource_id, sizeof(resource_id)) != sizeof(resource_id)) { dbg("error setting uid from existing uid map file"); return -1; } rval = build_uid_map_data(file); close(file); if (rval < 0) return -1; /* return from successful initialization from existing uid map file */ return 0;}/* * build_uid_map_data: used by uid_map_from_file(), recursively * reads map file and builds two hash tables and EP_XREF data * structures * * @file: key into a GHashTable * * Return value: success 0, error -1. */static gint build_uid_map_data(int file){ int rval; EP_XREF *ep_xref; EP_XREF ep_xref1; gpointer value; gpointer key; rval = read(file, &ep_xref1, sizeof(EP_XREF)); while ( (rval != EOF) && (rval == sizeof(EP_XREF)) ) { /* copy read record from ep_xref1 to malloc'd ep_xref */ ep_xref = (EP_XREF *)g_malloc0(sizeof(EP_XREF)); if (!ep_xref) return -1; memcpy(ep_xref, &ep_xref1, sizeof(EP_XREF)); value = (gpointer)ep_xref; /* entity path based key */ key = (gpointer)&ep_xref->entity_path; g_hash_table_insert(oh_ep_table, key, value); /* resource id based key */ key = (gpointer)&ep_xref->resource_id; g_hash_table_insert(oh_resource_id_table, key, value); rval = read(file, &ep_xref1, sizeof(EP_XREF)); } /* TODO thought EOF would return -1, its not so check other way */ /* if (rval != EOF), rval of 0 seems to be EOF */ if ( (rval > 0) && (rval < sizeof(EP_XREF)) ) { dbg("error building ep xref from map file"); return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -