| /* |
| * Host Resources MIB - partition device group implementation - hr_partition.c |
| * |
| */ |
| /* Portions of this file are subject to the following copyright(s). See |
| * the Net-SNMP's COPYING file for more details and other copyrights |
| * that may apply: |
| */ |
| /* |
| * Portions of this file are copyrighted by: |
| * Copyright (C) 2007 Apple, Inc. All rights reserved. |
| * Use is subject to license terms specified in the COPYING file |
| * distributed with the Net-SNMP package. |
| */ |
| |
| #include <net-snmp/net-snmp-config.h> |
| #include <fcntl.h> |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #include <errno.h> |
| |
| #include "host_res.h" |
| #include "hr_partition.h" |
| #include "hr_filesys.h" |
| #include "hr_disk.h" |
| |
| #include <sys/stat.h> |
| |
| #define HRP_MONOTONICALLY_INCREASING |
| |
| /********************* |
| * |
| * Kernel & interface information, |
| * and internal forward declarations |
| * |
| *********************/ |
| |
| static int HRP_savedDiskIndex; |
| static int HRP_savedPartIndex; |
| static char HRP_savedName[1024]; |
| #ifdef NETSNMP_CAN_GET_DISK_LABEL |
| static char HRP_savedLabel[1024]; |
| #endif |
| |
| static int HRP_DiskIndex; |
| |
| static void Save_HR_Partition(int, int); |
| |
| |
| /********************* |
| * |
| * Initialisation & common implementation functions |
| * |
| *********************/ |
| |
| static void Init_HR_Partition(void); |
| static int Get_Next_HR_Partition(void); |
| int header_hrpartition(struct variable *, oid *, size_t *, int, |
| size_t *, WriteMethod **); |
| |
| |
| #define HRPART_INDEX 1 |
| #define HRPART_LABEL 2 |
| #define HRPART_ID 3 |
| #define HRPART_SIZE 4 |
| #define HRPART_FSIDX 5 |
| |
| struct variable4 hrpartition_variables[] = { |
| {HRPART_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_hrpartition, 2, {1, 1}}, |
| {HRPART_LABEL, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, |
| var_hrpartition, 2, {1, 2}}, |
| {HRPART_ID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, |
| var_hrpartition, 2, {1, 3}}, |
| {HRPART_SIZE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_hrpartition, 2, {1, 4}}, |
| {HRPART_FSIDX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, |
| var_hrpartition, 2, {1, 5}} |
| }; |
| oid hrpartition_variables_oid[] = |
| { 1, 3, 6, 1, 2, 1, 25, 3, 7 }; |
| |
| |
| void |
| init_hr_partition(void) |
| { |
| REGISTER_MIB("host/hr_partition", hrpartition_variables, variable4, |
| hrpartition_variables_oid); |
| } |
| |
| |
| /* |
| * header_hrpartition(... |
| * Arguments: |
| * vp IN - pointer to variable entry that points here |
| * name IN/OUT - IN/name requested, OUT/name found |
| * length IN/OUT - length of IN/OUT oid's |
| * exact IN - TRUE if an exact match was requested |
| * var_len OUT - length of variable or 0 if function returned |
| * write_method |
| * |
| */ |
| |
| int |
| header_hrpartition(struct variable *vp, |
| oid * name, |
| size_t * length, |
| int exact, |
| size_t * var_len, WriteMethod ** write_method) |
| { |
| #define HRPART_DISK_NAME_LENGTH 11 |
| #define HRPART_ENTRY_NAME_LENGTH 12 |
| oid newname[MAX_OID_LEN]; |
| int part_idx, LowDiskIndex = -1, LowPartIndex = -1; |
| int result; |
| |
| DEBUGMSGTL(("host/hr_partition", "var_hrpartition: ")); |
| DEBUGMSGOID(("host/hr_partition", name, *length)); |
| DEBUGMSG(("host/hr_partition", " %d\n", exact)); |
| |
| memcpy((char *) newname, (char *) vp->name, |
| (int) vp->namelen * sizeof(oid)); |
| /* |
| * Find "next" partition entry |
| */ |
| |
| Init_HR_Disk(); |
| Init_HR_Partition(); |
| |
| /* |
| * Find the "next" disk and partition entries. |
| * If we're in the middle of the table, then there's |
| * no point in examining earlier disks, so set the |
| * starting disk to that of the variable being queried. |
| * |
| * If we've moved from one column of the table to another, |
| * then we need to start at the beginning again. |
| * (i.e. the 'compare' fails to match) |
| * Similarly if we're at the start of the table |
| * (i.e. *length is too short to be a full instance) |
| */ |
| |
| if ((snmp_oid_compare(vp->name, vp->namelen, name, vp->namelen) == 0) |
| && (*length > HRPART_DISK_NAME_LENGTH)) { |
| LowDiskIndex = |
| (name[HRPART_DISK_NAME_LENGTH] & |
| ((1 << HRDEV_TYPE_SHIFT) - 1)); |
| |
| DEBUGMSGTL(("host/hr_partition", "... low index %d\n", LowDiskIndex)); |
| while (HRP_DiskIndex < LowDiskIndex) { |
| Init_HR_Partition(); /* moves to next disk */ |
| if (HRP_DiskIndex == -1) |
| return (MATCH_FAILED); |
| } |
| } |
| |
| for (;;) { |
| part_idx = Get_Next_HR_Partition(); |
| DEBUGMSGTL(("host/hr_partition", "... part index %d\n", part_idx)); |
| if (part_idx == 0) |
| break; |
| newname[HRPART_DISK_NAME_LENGTH] = |
| (HRDEV_DISK << HRDEV_TYPE_SHIFT) + HRP_DiskIndex; |
| newname[HRPART_ENTRY_NAME_LENGTH] = part_idx; |
| result = snmp_oid_compare(name, *length, newname, vp->namelen + 2); |
| if (exact && (result == 0)) { |
| Save_HR_Partition(HRP_DiskIndex, part_idx); |
| LowDiskIndex = HRP_DiskIndex; |
| LowPartIndex = part_idx; |
| break; |
| } |
| if (!exact && (result < 0)) { |
| if (LowPartIndex == -1) { |
| Save_HR_Partition(HRP_DiskIndex, part_idx); |
| LowDiskIndex = HRP_DiskIndex; |
| LowPartIndex = part_idx; |
| } else if (LowDiskIndex < HRP_DiskIndex) |
| break; |
| else if (part_idx < LowPartIndex) { |
| Save_HR_Partition(HRP_DiskIndex, part_idx); |
| LowDiskIndex = HRP_DiskIndex; |
| LowPartIndex = part_idx; |
| } |
| #ifdef HRP_MONOTONICALLY_INCREASING |
| break; |
| #endif |
| } |
| } |
| |
| if (LowPartIndex == -1) { |
| DEBUGMSGTL(("host/hr_partition", "... index out of range\n")); |
| return (MATCH_FAILED); |
| } |
| |
| newname[HRPART_DISK_NAME_LENGTH] = |
| (HRDEV_DISK << HRDEV_TYPE_SHIFT) + LowDiskIndex; |
| newname[HRPART_ENTRY_NAME_LENGTH] = LowPartIndex; |
| memcpy((char *) name, (char *) newname, |
| ((int) vp->namelen + 2) * sizeof(oid)); |
| *length = vp->namelen + 2; |
| *write_method = (WriteMethod*)0; |
| *var_len = sizeof(long); /* default to 'long' results */ |
| |
| DEBUGMSGTL(("host/hr_partition", "... get partition stats ")); |
| DEBUGMSGOID(("host/hr_partition", name, *length)); |
| DEBUGMSG(("host/hr_partition", "\n")); |
| return LowPartIndex; |
| } |
| |
| |
| /********************* |
| * |
| * System specific implementation functions |
| * |
| *********************/ |
| |
| |
| u_char * |
| var_hrpartition(struct variable * vp, |
| oid * name, |
| size_t * length, |
| int exact, size_t * var_len, WriteMethod ** write_method) |
| { |
| int part_idx; |
| static char string[1024]; |
| struct stat stat_buf; |
| |
| part_idx = |
| header_hrpartition(vp, name, length, exact, var_len, write_method); |
| if (part_idx == MATCH_FAILED) |
| return NULL; |
| |
| if (stat(HRP_savedName, &stat_buf) == -1) |
| return NULL; |
| |
| switch (vp->magic) { |
| case HRPART_INDEX: |
| long_return = part_idx; |
| return (u_char *) & long_return; |
| case HRPART_LABEL: |
| #ifdef NETSNMP_CAN_GET_DISK_LABEL |
| *var_len = strlen(HRP_savedLabel); |
| return (u_char *) HRP_savedLabel; |
| #else |
| *var_len = strlen(HRP_savedName); |
| return (u_char *) HRP_savedName; |
| #endif |
| case HRPART_ID: /* Use the device number */ |
| sprintf(string, "0x%x", (int) stat_buf.st_rdev); |
| *var_len = strlen(string); |
| return (u_char *) string; |
| case HRPART_SIZE: |
| /* |
| * XXX - based on single partition assumption |
| */ |
| long_return = Get_FSSize(HRP_savedName); |
| return (u_char *) & long_return; |
| case HRPART_FSIDX: |
| long_return = Get_FSIndex(HRP_savedName); |
| return (u_char *) & long_return; |
| default: |
| DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrpartition\n", |
| vp->magic)); |
| } |
| return NULL; |
| } |
| |
| |
| /********************* |
| * |
| * Internal implementation functions |
| * |
| *********************/ |
| |
| static int HRP_index; |
| |
| static void |
| Init_HR_Partition(void) |
| { |
| DEBUGMSGTL(("host/hr_partition", "Init_HR_Partition\n")); |
| HRP_DiskIndex = Get_Next_HR_Disk(); |
| if (HRP_DiskIndex != -1) |
| HRP_DiskIndex &= ((1 << HRDEV_TYPE_SHIFT) - 1); |
| DEBUGMSGTL(("host/hr_partition", "... %d\n",HRP_DiskIndex)); |
| |
| HRP_index = -1; |
| } |
| |
| static int |
| Get_Next_HR_Partition(void) |
| { |
| char string[1024]; |
| int fd; |
| |
| DEBUGMSGTL(("host/hr_partition", "Get_Next_HR_Partition %d\n",HRP_DiskIndex)); |
| if (HRP_DiskIndex == -1) { |
| return 0; |
| } |
| |
| HRP_index++; |
| while (Get_Next_HR_Disk_Partition(string, sizeof(string), HRP_index) != -1) { |
| DEBUGMSGTL(("host/hr_partition", |
| "Get_Next_HR_Partition: %s (:%d)\n", |
| string, HRP_index)); |
| |
| #ifdef O_NDELAY |
| fd = open(string, O_RDONLY|O_NDELAY); |
| #else |
| fd = open(string, O_RDONLY); |
| #endif |
| if (fd != -1) { |
| close(fd); |
| return HRP_index + 1; |
| } else if (errno == EBUSY) { |
| return HRP_index + 1; |
| } |
| HRP_index++; |
| } |
| |
| /* |
| * Finished with this disk, try the next |
| */ |
| Init_HR_Partition(); |
| return (Get_Next_HR_Partition()); |
| } |
| |
| static void |
| Save_HR_Partition(int disk_idx, int part_idx) |
| { |
| HRP_savedDiskIndex = disk_idx; |
| HRP_savedPartIndex = part_idx; |
| (void) Get_Next_HR_Disk_Partition(HRP_savedName, sizeof(HRP_savedName), HRP_index); |
| #ifdef NETSNMP_CAN_GET_DISK_LABEL |
| (void) Get_HR_Disk_Label(HRP_savedLabel, sizeof(HRP_savedLabel), HRP_savedName); |
| #endif |
| } |