summaryrefslogtreecommitdiff
path: root/agent/mibgroup/host/hr_partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/host/hr_partition.c')
-rw-r--r--agent/mibgroup/host/hr_partition.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/agent/mibgroup/host/hr_partition.c b/agent/mibgroup/host/hr_partition.c
new file mode 100644
index 0000000..abe7692
--- /dev/null
+++ b/agent/mibgroup/host/hr_partition.c
@@ -0,0 +1,342 @@
+/*
+ * 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
+}