diff options
author | Peter Schiffer <pschiffe@redhat.com> | 2013-10-31 16:43:54 +0100 |
---|---|---|
committer | Peter Schiffer <pschiffe@redhat.com> | 2013-11-05 15:16:07 +0100 |
commit | 268cc0805bb2b580aa6734656fd698bf54523d6c (patch) | |
tree | cdcf9ad4a911a03171d33a5cee565da6c3a03272 | |
parent | 4f6220c7c311165fcdf943268fc0a87788e87fb5 (diff) | |
download | openlmi-providers-268cc0805bb2b580aa6734656fd698bf54523d6c.tar.gz openlmi-providers-268cc0805bb2b580aa6734656fd698bf54523d6c.tar.xz openlmi-providers-268cc0805bb2b580aa6734656fd698bf54523d6c.zip |
Hardware: Added Physical Disk Provider
New Provider:
* LMI_DiskPhysicalPackage
-rw-r--r-- | mof/60_LMI_Hardware.mof | 9 | ||||
-rw-r--r-- | openlmi-providers.spec | 8 | ||||
-rw-r--r-- | src/hardware/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/hardware/LMI_DiskPhysicalPackageProvider.c | 206 | ||||
-rw-r--r-- | src/hardware/LMI_Hardware.h | 1 | ||||
-rw-r--r-- | src/hardware/dmidecode.h | 2 | ||||
-rw-r--r-- | src/hardware/smartctl.c | 270 | ||||
-rw-r--r-- | src/hardware/smartctl.h | 60 | ||||
-rw-r--r-- | src/hardware/sysfs.c | 12 | ||||
-rw-r--r-- | src/hardware/sysfs.h | 16 |
10 files changed, 570 insertions, 15 deletions
diff --git a/mof/60_LMI_Hardware.mof b/mof/60_LMI_Hardware.mof index 74e1ee5..adef642 100644 --- a/mof/60_LMI_Hardware.mof +++ b/mof/60_LMI_Hardware.mof @@ -449,3 +449,12 @@ class LMI_PCIBridgeSystemDevice: CIM_SystemDevice [Override("PartComponent")] LMI_PCIBridge REF PartComponent; }; + +/****************************************************************************** + * Disks + */ + +[ Version("0.5.0"), Provider("cmpi:cmpiLMI_DiskPhysicalPackage") ] +class LMI_DiskPhysicalPackage: CIM_PhysicalPackage +{ +}; diff --git a/openlmi-providers.spec b/openlmi-providers.spec index 34e4e29..d4eeffc 100644 --- a/openlmi-providers.spec +++ b/openlmi-providers.spec @@ -3,7 +3,7 @@ Name: openlmi-providers Version: 0.4.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Set of basic CIM providers License: LGPLv2+ @@ -144,6 +144,7 @@ Requires: %{name}%{?_isa} = %{version}-%{release} Requires: dmidecode %endif Requires: util-linux +Requires: smartmontools %description -n openlmi-hardware %{summary}. @@ -885,7 +886,10 @@ if [ "$1" -eq 0 ]; then fi >> %logfile 2>&1 %changelog -* Mon Nov 04 2013 Radek Novacek <rnovacek@redhat.com> 0.4.1-3 +* Tue Nov 05 2013 Peter Schiffer <pschiffe@redhat.com> 0.4.1-2 +- Added dependency on smartmontools to hardware subpackage + +* Mon Nov 04 2013 Radek Novacek <rnovacek@redhat.com> 0.4.1-1 - Version 0.4.1 - Add powermanagement and hardware providers documentation - Require cim-schema diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt index 8ccf649..d0272a0 100644 --- a/src/hardware/CMakeLists.txt +++ b/src/hardware/CMakeLists.txt @@ -10,6 +10,7 @@ set(provider_SRCS procfs.c sysfs.c PCIDev.c + smartctl.c ) konkretcmpi_generate(${MOF} diff --git a/src/hardware/LMI_DiskPhysicalPackageProvider.c b/src/hardware/LMI_DiskPhysicalPackageProvider.c new file mode 100644 index 0000000..a2945f1 --- /dev/null +++ b/src/hardware/LMI_DiskPhysicalPackageProvider.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Peter Schiffer <pschiffe@redhat.com> + */ + +#include <konkret/konkret.h> +#include "LMI_DiskPhysicalPackage.h" +#include "LMI_Hardware.h" +#include "globals.h" +#include "smartctl.h" + +static const CMPIBroker* _cb = NULL; + +static void LMI_DiskPhysicalPackageInitialize() +{ +} + +static CMPIStatus LMI_DiskPhysicalPackageCleanup( + CMPIInstanceMI* mi, + const CMPIContext* cc, + CMPIBoolean term) +{ + CMReturn(CMPI_RC_OK); +} + +static CMPIStatus LMI_DiskPhysicalPackageEnumInstanceNames( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop) +{ + return KDefaultEnumerateInstanceNames( + _cb, mi, cc, cr, cop); +} + +static CMPIStatus LMI_DiskPhysicalPackageEnumInstances( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const char** properties) +{ + LMI_DiskPhysicalPackage lmi_hdd; + const char *ns = KNameSpace(cop); + unsigned i; + char instance_id[INSTANCE_ID_LEN]; + SmartctlHdd *smtcl_hdds = NULL; + unsigned smtcl_hdds_nb = 0; + + if (smartctl_get_hdds(&smtcl_hdds, &smtcl_hdds_nb) != 0 || smtcl_hdds_nb < 1) { + goto done; + } + + for (i = 0; i < smtcl_hdds_nb; i++) { + LMI_DiskPhysicalPackage_Init(&lmi_hdd, _cb, ns); + + LMI_DiskPhysicalPackage_Set_CreationClassName(&lmi_hdd, + ORGID "_" DISK_PHYS_PKG_CLASS_NAME); + LMI_DiskPhysicalPackage_Set_PackageType(&lmi_hdd, + LMI_DiskPhysicalPackage_PackageType_Storage_Media_Package_e_g___Disk_or_Tape_Drive); + + snprintf(instance_id, INSTANCE_ID_LEN, + ORGID ":" ORGID "_" DISK_PHYS_PKG_CLASS_NAME ":%s", + smtcl_hdds[i].serial_number); + + LMI_DiskPhysicalPackage_Set_Tag(&lmi_hdd, smtcl_hdds[i].serial_number); + LMI_DiskPhysicalPackage_Set_Manufacturer(&lmi_hdd, + smtcl_hdds[i].manufacturer); + LMI_DiskPhysicalPackage_Set_Model(&lmi_hdd, smtcl_hdds[i].model); + LMI_DiskPhysicalPackage_Set_SerialNumber(&lmi_hdd, + smtcl_hdds[i].serial_number); + LMI_DiskPhysicalPackage_Set_Caption(&lmi_hdd, "Physical Disk Package"); + LMI_DiskPhysicalPackage_Set_Description(&lmi_hdd, + "This object represents one physical disk package in system."); + LMI_DiskPhysicalPackage_Set_Name(&lmi_hdd, smtcl_hdds[i].name); + LMI_DiskPhysicalPackage_Set_ElementName(&lmi_hdd, smtcl_hdds[i].name); + LMI_DiskPhysicalPackage_Set_InstanceID(&lmi_hdd, instance_id); + + KReturnInstance(cr, lmi_hdd); + } + +done: + smartctl_free_hdds(&smtcl_hdds, &smtcl_hdds_nb); + + CMReturn(CMPI_RC_OK); +} + +static CMPIStatus LMI_DiskPhysicalPackageGetInstance( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const char** properties) +{ + return KDefaultGetInstance( + _cb, mi, cc, cr, cop, properties); +} + +static CMPIStatus LMI_DiskPhysicalPackageCreateInstance( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const CMPIInstance* ci) +{ + CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); +} + +static CMPIStatus LMI_DiskPhysicalPackageModifyInstance( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const CMPIInstance* ci, + const char** properties) +{ + CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); +} + +static CMPIStatus LMI_DiskPhysicalPackageDeleteInstance( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop) +{ + CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); +} + +static CMPIStatus LMI_DiskPhysicalPackageExecQuery( + CMPIInstanceMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const char* lang, + const char* query) +{ + CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); +} + +CMInstanceMIStub( + LMI_DiskPhysicalPackage, + LMI_DiskPhysicalPackage, + _cb, + LMI_DiskPhysicalPackageInitialize()) + +static CMPIStatus LMI_DiskPhysicalPackageMethodCleanup( + CMPIMethodMI* mi, + const CMPIContext* cc, + CMPIBoolean term) +{ + CMReturn(CMPI_RC_OK); +} + +static CMPIStatus LMI_DiskPhysicalPackageInvokeMethod( + CMPIMethodMI* mi, + const CMPIContext* cc, + const CMPIResult* cr, + const CMPIObjectPath* cop, + const char* meth, + const CMPIArgs* in, + CMPIArgs* out) +{ + return LMI_DiskPhysicalPackage_DispatchMethod( + _cb, mi, cc, cr, cop, meth, in, out); +} + +CMMethodMIStub( + LMI_DiskPhysicalPackage, + LMI_DiskPhysicalPackage, + _cb, + LMI_DiskPhysicalPackageInitialize()) + +KUint32 LMI_DiskPhysicalPackage_IsCompatible( + const CMPIBroker* cb, + CMPIMethodMI* mi, + const CMPIContext* context, + const LMI_DiskPhysicalPackageRef* self, + const KRef* ElementToCheck, + CMPIStatus* status) +{ + KUint32 result = KUINT32_INIT; + + KSetStatus(status, ERR_NOT_SUPPORTED); + return result; +} + +KONKRET_REGISTRATION( + "root/cimv2", + "LMI_DiskPhysicalPackage", + "LMI_DiskPhysicalPackage", + "instance method") diff --git a/src/hardware/LMI_Hardware.h b/src/hardware/LMI_Hardware.h index 0ea6237..6ca6ab2 100644 --- a/src/hardware/LMI_Hardware.h +++ b/src/hardware/LMI_Hardware.h @@ -46,5 +46,6 @@ const char *provider_name; #define BATTERY_PHYS_PKG_CLASS_NAME "BatteryPhysicalPackage" #define PCI_DEVICE_CLASS_NAME "PCIDevice" #define PCI_BRIDGE_CLASS_NAME "PCIBridge" +#define DISK_PHYS_PKG_CLASS_NAME "DiskPhysicalPackage" #endif /* LMI_HARDWARE_H_ */ diff --git a/src/hardware/dmidecode.h b/src/hardware/dmidecode.h index d139f38..e293cde 100644 --- a/src/hardware/dmidecode.h +++ b/src/hardware/dmidecode.h @@ -160,7 +160,7 @@ typedef struct _DmiBattery { /* * Get array of processors according to the dmidecode program. - * @param cpu array of cpus, this function will allocate necessary memory, + * @param cpus array of cpus, this function will allocate necessary memory, * but caller is responsible for freeing it * @param cpus_nb number of processors in cpus * @return 0 if success, negative value otherwise diff --git a/src/hardware/smartctl.c b/src/hardware/smartctl.c new file mode 100644 index 0000000..750dea6 --- /dev/null +++ b/src/hardware/smartctl.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Peter Schiffer <pschiffe@redhat.com> + */ + +#include "smartctl.h" + +/* + * Initialize SmartctlHdd attributes. + * @param hdd + */ +void init_smctlhdd_struct(SmartctlHdd *hdd) +{ + hdd->dev_path = NULL; + hdd->dev_basename = NULL; + hdd->manufacturer = NULL; + hdd->model = NULL; + hdd->serial_number = NULL; + hdd->name = NULL; +} + +/* + * Check attributes of hdd structure and fill in defaults if needed. + * @param hdd + * @return 0 if success, negative value otherwise + */ +short check_smctlhdd_attributes(SmartctlHdd *hdd) +{ + short ret = -1; + + if (!hdd->dev_path) { + if (!(hdd->dev_path = strdup(""))) { + goto done; + } + } + if (!hdd->dev_basename) { + if (!(hdd->dev_basename = strdup(""))) { + goto done; + } + } + if (!hdd->manufacturer) { + if (!(hdd->manufacturer = strdup(""))) { + goto done; + } + } + if (!hdd->model) { + if (!(hdd->model = strdup(""))) { + goto done; + } + } + if (!hdd->serial_number) { + if (!(hdd->serial_number = strdup(""))) { + goto done; + } + } + if (!hdd->name) { + if (!(hdd->name = strdup(""))) { + goto done; + } + } + + ret = 0; + +done: + if (ret != 0) { + warn("Failed to allocate memory."); + } + + return ret; +} + +short scan_smctlhdd_devices(SmartctlHdd **hdds, unsigned *hdds_nb) +{ + short ret = -1; + unsigned i, curr_hdd = 0, buffer_size = 0, sec_buffer_size = 0; + char **buffer = NULL, **sec_buffer = NULL; + struct stat sb; + + smartctl_free_hdds(hdds, hdds_nb); + + /* get smartctl output */ + if (run_command("smartctl --scan", &buffer, &buffer_size) != 0) { + goto done; + } + + /* count hard drives - one line of output is one device */ + *hdds_nb = buffer_size; + + /* if no hard drive was found */ + if (*hdds_nb < 1) { + warn("Smartctl didn't recognize any hard drive."); + goto done; + } + + /* allocate memory for hard drives */ + *hdds = (SmartctlHdd *)calloc(*hdds_nb, sizeof(SmartctlHdd)); + if (!(*hdds)) { + warn("Failed to allocate memory."); + *hdds_nb = 0; + goto done; + } + + /* parse hard drive's dev path */ + for (i = 0; i < buffer_size; i++) { + init_smctlhdd_struct(&(*hdds)[i]); + + if (explode(buffer[i], NULL, &sec_buffer, &sec_buffer_size) != 0 || + sec_buffer_size < 1) { + free_2d_buffer(&sec_buffer, &sec_buffer_size); + continue; + } + + if (stat(sec_buffer[0], &sb) != 0) { + warn("Stat() call on file \"%s\" failed: %s", + sec_buffer[0], strerror(errno)); + free_2d_buffer(&sec_buffer, &sec_buffer_size); + continue; + } + + if ((sb.st_mode & S_IFMT) != S_IFBLK) { + warn("File \"%s\" is not a block device.", sec_buffer[0]); + free_2d_buffer(&sec_buffer, &sec_buffer_size); + continue; + } + + (*hdds)[curr_hdd].dev_path = strdup(sec_buffer[0]); + (*hdds)[curr_hdd].dev_basename = strdup(basename(sec_buffer[0])); + if (!(*hdds)[curr_hdd].dev_path || !(*hdds)[curr_hdd].dev_basename) { + warn("Failed to allocate memory."); + free_2d_buffer(&sec_buffer, &sec_buffer_size); + continue; + } + + curr_hdd++; + free_2d_buffer(&sec_buffer, &sec_buffer_size); + } + + if (curr_hdd != *hdds_nb) { + warn("There's some \"smartctl --scan\" output mismatch, " + "not all reported drives were processed."); + SmartctlHdd *tmp_hdd = (SmartctlHdd *)realloc(*hdds, + curr_hdd * sizeof(SmartctlHdd)); + if (!tmp_hdd) { + warn("Failed to allocate memory."); + goto done; + } + *hdds = tmp_hdd; + *hdds_nb = curr_hdd; + } + + ret = 0; + +done: + free_2d_buffer(&buffer, &buffer_size); + + if (ret != 0) { + smartctl_free_hdds(hdds, hdds_nb); + } + + return ret; +} + +short smartctl_get_hdds(SmartctlHdd **hdds, unsigned *hdds_nb) +{ + short ret = -1; + unsigned i, curr_hdd, buffer_size = 0; + char **buffer = NULL, *buf; + + if (scan_smctlhdd_devices(hdds, hdds_nb) != 0) { + goto done; + } + + for (curr_hdd = 0; curr_hdd < *hdds_nb; curr_hdd++) { + /* get smartctl output */ + char command[PATH_MAX]; + snprintf(command, PATH_MAX, "smartctl -i %s", + (*hdds)[curr_hdd].dev_path); + if (run_command(command, &buffer, &buffer_size) != 0) { + continue; + } + + /* parse information about hard drives */ + for (i = 0; i < buffer_size; i++) { + /* Model */ + buf = copy_string_part_after_delim(buffer[i], "Device Model:"); + if (buf) { + (*hdds)[curr_hdd].model = buf; + buf = NULL; + continue; + } + /* Serial Number */ + buf = copy_string_part_after_delim(buffer[i], "Serial Number:"); + if (buf) { + (*hdds)[curr_hdd].serial_number = buf; + buf = NULL; + continue; + } + /* Name */ + buf = copy_string_part_after_delim(buffer[i], "Model Family:"); + if (buf) { + (*hdds)[curr_hdd].name = buf; + buf = NULL; + continue; + } + } + + free_2d_buffer(&buffer, &buffer_size); + + /* get vendor from sysfs */ + char sysfs_path[PATH_MAX]; + snprintf(sysfs_path, PATH_MAX, SYSFS_BLOCK_PATH "/%s/device/vendor", + (*hdds)[curr_hdd].dev_basename); + path_get_string(sysfs_path, &(*hdds)[curr_hdd].manufacturer); + + /* fill in default attributes if needed */ + if (check_smctlhdd_attributes(&(*hdds)[curr_hdd]) != 0) { + goto done; + } + } + + ret = 0; + +done: + if (ret != 0) { + smartctl_free_hdds(hdds, hdds_nb); + } + + return ret; +} + +void smartctl_free_hdds(SmartctlHdd **hdds, unsigned *hdds_nb) +{ + unsigned i; + + if (*hdds && *hdds_nb > 0) { + for (i = 0; i < *hdds_nb; i++) { + free((*hdds)[i].dev_path); + (*hdds)[i].dev_path = NULL; + free((*hdds)[i].dev_basename); + (*hdds)[i].dev_basename = NULL; + free((*hdds)[i].manufacturer); + (*hdds)[i].manufacturer = NULL; + free((*hdds)[i].model); + (*hdds)[i].model = NULL; + free((*hdds)[i].serial_number); + (*hdds)[i].serial_number = NULL; + free((*hdds)[i].name); + (*hdds)[i].name = NULL; + } + free(*hdds); + } + + *hdds_nb = 0; + *hdds = NULL; +} diff --git a/src/hardware/smartctl.h b/src/hardware/smartctl.h new file mode 100644 index 0000000..5880e3a --- /dev/null +++ b/src/hardware/smartctl.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Peter Schiffer <pschiffe@redhat.com> + */ + +#ifndef SMARTCTL_H_ +#define SMARTCTL_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <sys/stat.h> +#include <sys/types.h> +#include "utils.h" +#include "sysfs.h" + +/* HDD from smartctl. */ +typedef struct _SmartctlHdd { + char *dev_path; /* /dev/path */ + char *dev_basename; /* basename of /dev/path */ + char *manufacturer; /* Manufacturer */ + char *model; /* Model */ + char *serial_number; /* Serial Number */ + char *name; /* Name */ +} SmartctlHdd; + +/* + * Get array of hard drives according to the smartclt program. + * @param hdds array of hdds, this function will allocate necessary memory, + * but caller is responsible for freeing it + * @param hdds_nb number of hard drives in hdds + * @return 0 if success, negative value otherwise + */ +short smartctl_get_hdds(SmartctlHdd **hdds, unsigned *hdds_nb); + +/* + * Free array of hard drive structures. + * @param hdds array of hdds + * @param hdds_nb number of hdds + */ +void smartctl_free_hdds(SmartctlHdd **hdds, unsigned *hdds_nb); + +#endif /* SMARTCTL_H_ */ diff --git a/src/hardware/sysfs.c b/src/hardware/sysfs.c index 4410ff7..aab2ba6 100644 --- a/src/hardware/sysfs.c +++ b/src/hardware/sysfs.c @@ -21,12 +21,6 @@ #include "sysfs.h" -/* - * Read unsigned value from file. - * @param path of file - * @paratm result - * @return 0 if success, negative value otherwise - */ short path_get_unsigned(const char *path, unsigned *result) { short ret = -1; @@ -54,12 +48,6 @@ done: return ret; } -/* - * Read string value from file. - * @param path of file - * @paratm result - * @return 0 if success, negative value otherwise - */ short path_get_string(const char *path, char **result) { short ret = -1; diff --git a/src/hardware/sysfs.h b/src/hardware/sysfs.h index 6ff7085..5fbe6a1 100644 --- a/src/hardware/sysfs.h +++ b/src/hardware/sysfs.h @@ -36,6 +36,7 @@ #define SYSFS_PATH "/sys/devices/system" #define SYSFS_CPU_PATH SYSFS_PATH "/cpu" #define SYSFS_KERNEL_MM "/sys/kernel/mm" +#define SYSFS_BLOCK_PATH "/sys/class/block" /* Transparent memory huge pages statuses. */ @@ -58,6 +59,21 @@ typedef struct _SysfsCpuCache { unsigned line_size; /* Cache Line Size */ } SysfsCpuCache; +/* + * Read unsigned value from file. + * @param path of file + * @paratm result + * @return 0 if success, negative value otherwise + */ +short path_get_unsigned(const char *path, unsigned *result); + +/* + * Read string value from file. + * @param path of file + * @paratm result + * @return 0 if success, negative value otherwise + */ +short path_get_string(const char *path, char **result); /* * Get array of processor caches from sysfs. |