summaryrefslogtreecommitdiff
path: root/agent/mibgroup/host/hr_disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/host/hr_disk.c')
-rw-r--r--agent/mibgroup/host/hr_disk.c1024
1 files changed, 1024 insertions, 0 deletions
diff --git a/agent/mibgroup/host/hr_disk.c b/agent/mibgroup/host/hr_disk.c
new file mode 100644
index 0000000..e4c5b95
--- /dev/null
+++ b/agent/mibgroup/host/hr_disk.c
@@ -0,0 +1,1024 @@
+/*
+ * Host Resources MIB - disk device group implementation - hr_disk.c
+ *
+ */
+
+#include <net-snmp/net-snmp-config.h>
+#include "host_res.h"
+#include "hr_disk.h"
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#include <fcntl.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_KVM_H
+#include <kvm.h>
+#endif
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#else
+# define dirent direct
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+#if HAVE_SYS_DKIO_H
+#include <sys/dkio.h>
+#endif
+#if HAVE_SYS_DISKIO_H /* HP-UX only ? */
+#include <sys/diskio.h>
+#endif
+#if HAVE_LINUX_HDREG_H
+#include <linux/hdreg.h>
+#endif
+#if HAVE_SYS_DISKLABEL_H
+#define DKTYPENAMES
+#include <sys/disklabel.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifdef linux
+/*
+ * define BLKGETSIZE from <linux/fs.h>:
+ * Note: cannot include this file completely due to errors with redefinition
+ * of structures (at least with older linux versions) --jsf
+ */
+#define BLKGETSIZE _IO(0x12,96) /* return device size */
+#endif
+
+#include <net-snmp/agent/agent_read_config.h>
+#include <net-snmp/library/read_config.h>
+
+#define HRD_MONOTONICALLY_INCREASING
+
+ /*********************
+ *
+ * Kernel & interface information,
+ * and internal forward declarations
+ *
+ *********************/
+
+void Init_HR_Disk(void);
+int Get_Next_HR_Disk(void);
+int Get_Next_HR_Disk_Partition(char *, size_t, int);
+static void Add_HR_Disk_entry(const char *, int, int, int, int,
+ const char *, int, int);
+static void Save_HR_Disk_General(void);
+static void Save_HR_Disk_Specific(void);
+static int Query_Disk(int, const char *);
+static int Is_It_Writeable(void);
+static int What_Type_Disk(void);
+static int Is_It_Removeable(void);
+static const char *describe_disk(int);
+
+int header_hrdisk(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod **);
+
+static int HRD_type_index;
+static int HRD_index;
+static char HRD_savedModel[40];
+static long HRD_savedCapacity = 1044;
+static int HRD_savedFlags;
+static time_t HRD_history[HRDEV_TYPE_MASK + 1];
+
+#ifdef DIOC_DESCRIBE
+static disk_describe_type HRD_info;
+static capacity_type HRD_cap;
+
+static int HRD_savedIntf_type;
+static int HRD_savedDev_type;
+#endif
+
+#ifdef DKIOCINFO
+static struct dk_cinfo HRD_info;
+static struct dk_geom HRD_cap;
+
+static int HRD_savedCtrl_type;
+#endif
+
+#ifdef HAVE_LINUX_HDREG_H
+static struct hd_driveid HRD_info;
+#endif
+
+#ifdef DIOCGDINFO
+static struct disklabel HRD_info;
+#endif
+
+static void parse_disk_config(const char *, char *);
+static void free_disk_config(void);
+
+ /*********************
+ *
+ * Initialisation & common implementation functions
+ *
+ *********************/
+
+#define HRDISK_ACCESS 1
+#define HRDISK_MEDIA 2
+#define HRDISK_REMOVEABLE 3
+#define HRDISK_CAPACITY 4
+
+struct variable4 hrdisk_variables[] = {
+ {HRDISK_ACCESS, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 1}},
+ {HRDISK_MEDIA, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 2}},
+ {HRDISK_REMOVEABLE, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 3}},
+ {HRDISK_CAPACITY, ASN_INTEGER, RONLY, var_hrdisk, 2, {1, 4}}
+};
+oid hrdisk_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 6 };
+
+
+void
+init_hr_disk(void)
+{
+ int i;
+
+ init_device[HRDEV_DISK] = Init_HR_Disk;
+ next_device[HRDEV_DISK] = Get_Next_HR_Disk;
+ save_device[HRDEV_DISK] = Save_HR_Disk_General;
+#ifdef HRD_MONOTONICALLY_INCREASING
+ dev_idx_inc[HRDEV_DISK] = 1;
+#endif
+
+#if defined(linux)
+ Add_HR_Disk_entry("/dev/hd%c%d", -1, -1, 'a', 'l', "/dev/hd%c", 1, 15);
+ Add_HR_Disk_entry("/dev/sd%c%d", -1, -1, 'a', 'p', "/dev/sd%c", 1, 15);
+ Add_HR_Disk_entry("/dev/md%d", -1, -1, 0, 3, "/dev/md%d", 0, 0);
+ Add_HR_Disk_entry("/dev/fd%d", -1, -1, 0, 1, "/dev/fd%d", 0, 0);
+#elif defined(hpux)
+#if defined(hpux10) || defined(hpux11)
+ Add_HR_Disk_entry("/dev/rdsk/c%dt%xd%d", 0, 1, 0, 15,
+ "/dev/rdsk/c%dt%xd0", 0, 4);
+#else /* hpux9 */
+ Add_HR_Disk_entry("/dev/rdsk/c%dd%xs%d", 201, 201, 0, 15,
+ "/dev/rdsk/c%dd%xs0", 0, 4);
+#endif
+#elif defined(solaris2)
+ Add_HR_Disk_entry("/dev/rdsk/c%dt%dd0s%d", 0, 7, 0, 15,
+ "/dev/rdsk/c%dt%dd0s0", 0, 7);
+ Add_HR_Disk_entry("/dev/rdsk/c%dd%ds%d", 0, 7, 0, 15,
+ "/dev/rdsk/c%dd%ds0", 0, 7);
+#elif defined(freebsd4) || defined(freebsd5)
+ Add_HR_Disk_entry("/dev/ad%ds%d%c", 0, 1, 1, 4, "/dev/ad%ds%d", 'a', 'h');
+ Add_HR_Disk_entry("/dev/da%ds%d%c", 0, 1, 1, 4, "/dev/da%ds%d", 'a', 'h');
+#elif defined(freebsd3)
+ Add_HR_Disk_entry("/dev/wd%ds%d%c", 0, 1, 1, 4, "/dev/wd%ds%d", 'a',
+ 'h');
+ Add_HR_Disk_entry("/dev/sd%ds%d%c", 0, 1, 1, 4, "/dev/sd%ds%d", 'a',
+ 'h');
+#elif defined(freebsd2)
+ Add_HR_Disk_entry("/dev/wd%d%c", -1, -1, 0, 3, "/dev/wd%d", 'a', 'h');
+ Add_HR_Disk_entry("/dev/sd%d%c", -1, -1, 0, 3, "/dev/sd%d", 'a', 'h');
+#elif defined(netbsd1)
+ Add_HR_Disk_entry("/dev/wd%d%c", -1, -1, 0, 3, "/dev/wd%dc", 'a', 'h');
+ Add_HR_Disk_entry("/dev/sd%d%c", -1, -1, 0, 3, "/dev/sd%dc", 'a', 'h');
+#endif
+
+ device_descr[HRDEV_DISK] = describe_disk;
+ HRD_savedModel[0] = '\0';
+ HRD_savedCapacity = 0;
+
+ for (i = 0; i < HRDEV_TYPE_MASK; ++i)
+ HRD_history[i] = -1;
+
+ REGISTER_MIB("host/hr_disk", hrdisk_variables, variable4,
+ hrdisk_variables_oid);
+
+ snmpd_register_config_handler("ignoredisk", parse_disk_config,
+ free_disk_config, "name");
+}
+
+#define ITEM_STRING 1
+#define ITEM_SET 2
+#define ITEM_STAR 3
+#define ITEM_ANY 4
+
+typedef unsigned char details_set[32];
+
+typedef struct _conf_disk_item {
+ int item_type; /* ITEM_STRING, ITEM_SET, ITEM_STAR, ITEM_ANY */
+ void *item_details; /* content depends upon item_type */
+ struct _conf_disk_item *item_next;
+} conf_disk_item;
+
+typedef struct _conf_disk_list {
+ conf_disk_item *list_item;
+ struct _conf_disk_list *list_next;
+} conf_disk_list;
+static conf_disk_list *conf_list = NULL;
+
+static int match_disk_config(const char *);
+static int match_disk_config_item(const char *, conf_disk_item *);
+
+static void
+parse_disk_config(const char *token, char *cptr)
+{
+ conf_disk_list *d_new = 0;
+ conf_disk_item *di_curr = 0;
+ details_set *d_set = 0;
+ char *name = 0, *p = 0, *d_str = 0, c;
+ unsigned int i, neg, c1, c2;
+ char *st = 0;
+
+ name = strtok_r(cptr, " \t", &st);
+ if (!name) {
+ config_perror("Missing NAME parameter");
+ return;
+ }
+ d_new = (conf_disk_list *) malloc(sizeof(conf_disk_list));
+ if (!d_new) {
+ config_perror("Out of memory");
+ return;
+ }
+ di_curr = (conf_disk_item *) malloc(sizeof(conf_disk_item));
+ if (!di_curr) {
+ SNMP_FREE(d_new);
+ config_perror("Out of memory");
+ return;
+ }
+ d_new->list_item = di_curr;
+ /* XXX: on error/return conditions we need to free the entire new
+ list, not just the last node like this is doing! */
+ for (;;) {
+ if (*name == '?') {
+ di_curr->item_type = ITEM_ANY;
+ di_curr->item_details = (void *) 0;
+ name++;
+ } else if (*name == '*') {
+ di_curr->item_type = ITEM_STAR;
+ di_curr->item_details = (void *) 0;
+ name++;
+ } else if (*name == '[') {
+ d_set = (details_set *) malloc(sizeof(details_set));
+ if (!d_set) {
+ config_perror("Out of memory");
+ SNMP_FREE(d_new);
+ SNMP_FREE(di_curr);
+ SNMP_FREE(d_set);
+ SNMP_FREE(d_str);
+ return;
+ }
+ for (i = 0; i < sizeof(details_set); i++)
+ (*d_set)[i] = (unsigned char) 0;
+ name++;
+ if (*name == '^' || *name == '!') {
+ neg = 1;
+ name++;
+ } else {
+ neg = 0;
+ }
+ while (*name && *name != ']') {
+ c1 = ((unsigned int) *name++) & 0xff;
+ if (*name == '-' && *(name + 1) != ']') {
+ name++;
+ c2 = ((unsigned int) *name++) & 0xff;
+ } else {
+ c2 = c1;
+ }
+ for (i = c1; i <= c2; i++)
+ (*d_set)[i / 8] |= (unsigned char) (1 << (i % 8));
+ }
+ if (*name != ']') {
+ config_perror
+ ("Syntax error in NAME: invalid set specified");
+ SNMP_FREE(d_new);
+ SNMP_FREE(di_curr);
+ SNMP_FREE(d_set);
+ SNMP_FREE(d_str);
+ return;
+ }
+ if (neg) {
+ for (i = 0; i < sizeof(details_set); i++)
+ (*d_set)[i] = (*d_set)[i] ^ (unsigned char) 0xff;
+ }
+ di_curr->item_type = ITEM_SET;
+ di_curr->item_details = (void *) d_set;
+ name++;
+ } else {
+ for (p = name;
+ *p != '\0' && *p != '?' && *p != '*' && *p != '['; p++);
+ c = *p;
+ *p = '\0';
+ d_str = (char *) malloc(strlen(name) + 1);
+ if (!d_str) {
+ SNMP_FREE(d_new);
+ SNMP_FREE(d_str);
+ SNMP_FREE(di_curr);
+ SNMP_FREE(d_set);
+ config_perror("Out of memory");
+ return;
+ }
+ strcpy(d_str, name);
+ *p = c;
+ di_curr->item_type = ITEM_STRING;
+ di_curr->item_details = (void *) d_str;
+ name = p;
+ }
+ if (!*name) {
+ di_curr->item_next = (conf_disk_item *) 0;
+ break;
+ }
+ di_curr->item_next =
+ (conf_disk_item *) malloc(sizeof(conf_disk_item));
+ if (!di_curr->item_next) {
+ SNMP_FREE(di_curr->item_next);
+ SNMP_FREE(d_new);
+ SNMP_FREE(di_curr);
+ SNMP_FREE(d_set);
+ SNMP_FREE(d_str);
+ config_perror("Out of memory");
+ return;
+ }
+ di_curr = di_curr->item_next;
+ }
+ d_new->list_next = conf_list;
+ conf_list = d_new;
+}
+
+static void
+free_disk_config(void)
+{
+ conf_disk_list *d_ptr = conf_list, *d_next;
+ conf_disk_item *di_ptr, *di_next;
+
+ while (d_ptr) {
+ d_next = d_ptr->list_next;
+ di_ptr = d_ptr->list_item;
+ while (di_ptr) {
+ di_next = di_ptr->item_next;
+ if (di_ptr->item_details)
+ free(di_ptr->item_details);
+ free((void *) di_ptr);
+ di_ptr = di_next;
+ }
+ free((void *) d_ptr);
+ d_ptr = d_next;
+ }
+ conf_list = (conf_disk_list *) 0;
+}
+
+static int
+match_disk_config_item(const char *name, conf_disk_item * di_ptr)
+{
+ int result = 0;
+ size_t len;
+ details_set *d_set;
+ unsigned int c;
+
+ if (di_ptr) {
+ switch (di_ptr->item_type) {
+ case ITEM_STRING:
+ len = strlen((const char *) di_ptr->item_details);
+ if (!strncmp(name, (const char *) di_ptr->item_details, len))
+ result = match_disk_config_item(name + len,
+ di_ptr->item_next);
+ break;
+ case ITEM_SET:
+ if (*name) {
+ d_set = (details_set *) di_ptr->item_details;
+ c = ((unsigned int) *name) & 0xff;
+ if ((*d_set)[c / 8] & (unsigned char) (1 << (c % 8)))
+ result = match_disk_config_item(name + 1,
+ di_ptr->item_next);
+ }
+ break;
+ case ITEM_STAR:
+ if (di_ptr->item_next) {
+ for (; !result && *name; name++)
+ result = match_disk_config_item(name,
+ di_ptr->item_next);
+ } else {
+ result = 1;
+ }
+ break;
+ case ITEM_ANY:
+ if (*name)
+ result = match_disk_config_item(name + 1,
+ di_ptr->item_next);
+ break;
+ }
+ } else {
+ if (*name == '\0')
+ result = 1;
+ }
+
+ return result;
+}
+
+static int
+match_disk_config(const char *name)
+{
+ conf_disk_list *d_ptr = conf_list;
+
+ while (d_ptr) {
+ if (match_disk_config_item(name, d_ptr->list_item))
+ return 1; /* match found in ignorelist */
+ d_ptr = d_ptr->list_next;
+ }
+
+ /*
+ * no match in ignorelist
+ */
+ return 0;
+}
+
+/*
+ * header_hrdisk(...
+ * 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_hrdisk(struct variable *vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+#define HRDISK_ENTRY_NAME_LENGTH 11
+ oid newname[MAX_OID_LEN];
+ int disk_idx, LowIndex = -1;
+ int result;
+
+ DEBUGMSGTL(("host/hr_disk", "var_hrdisk: "));
+ DEBUGMSGOID(("host/hr_disk", name, *length));
+ DEBUGMSG(("host/hr_disk", " %d\n", exact));
+
+ memcpy((char *) newname, (char *) vp->name,
+ (int) vp->namelen * sizeof(oid));
+ /*
+ * Find "next" disk entry
+ */
+
+ Init_HR_Disk();
+ for (;;) {
+ disk_idx = Get_Next_HR_Disk();
+ if (disk_idx == -1)
+ break;
+ newname[HRDISK_ENTRY_NAME_LENGTH] = disk_idx;
+ result =
+ snmp_oid_compare(name, *length, newname,
+ (int) vp->namelen + 1);
+ if (exact && (result == 0)) {
+ LowIndex = disk_idx;
+ Save_HR_Disk_Specific();
+ break;
+ }
+ if ((!exact && (result < 0)) &&
+ (LowIndex == -1 || disk_idx < LowIndex)) {
+ LowIndex = disk_idx;
+ Save_HR_Disk_Specific();
+#ifdef HRD_MONOTONICALLY_INCREASING
+ break;
+#endif
+ }
+ }
+
+ if (LowIndex == -1) {
+ DEBUGMSGTL(("host/hr_disk", "... index out of range\n"));
+ return (MATCH_FAILED);
+ }
+
+ newname[HRDISK_ENTRY_NAME_LENGTH] = LowIndex;
+ memcpy((char *) name, (char *) newname,
+ ((int) vp->namelen + 1) * sizeof(oid));
+ *length = vp->namelen + 1;
+ *write_method = 0;
+ *var_len = sizeof(long); /* default to 'long' results */
+
+ DEBUGMSGTL(("host/hr_disk", "... get disk stats "));
+ DEBUGMSGOID(("host/hr_disk", name, *length));
+ DEBUGMSG(("host/hr_disk", "\n"));
+
+ return LowIndex;
+}
+
+
+ /*********************
+ *
+ * System specific implementation functions
+ *
+ *********************/
+
+
+u_char *
+var_hrdisk(struct variable * vp,
+ oid * name,
+ size_t * length,
+ int exact, size_t * var_len, WriteMethod ** write_method)
+{
+ int disk_idx;
+
+ disk_idx =
+ header_hrdisk(vp, name, length, exact, var_len, write_method);
+ if (disk_idx == MATCH_FAILED)
+ return NULL;
+
+
+ switch (vp->magic) {
+ case HRDISK_ACCESS:
+ long_return = Is_It_Writeable();
+ return (u_char *) & long_return;
+ case HRDISK_MEDIA:
+ long_return = What_Type_Disk();
+ return (u_char *) & long_return;
+ case HRDISK_REMOVEABLE:
+ long_return = Is_It_Removeable();
+ return (u_char *) & long_return;
+ case HRDISK_CAPACITY:
+ long_return = HRD_savedCapacity;
+ return (u_char *) & long_return;
+ default:
+ DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrdisk\n",
+ vp->magic));
+ }
+ return NULL;
+}
+
+
+ /*********************
+ *
+ * Internal implementation functions
+ *
+ *********************/
+
+#define MAX_NUMBER_DISK_TYPES 16 /* probably should be a variable */
+#define MAX_DISKS_PER_TYPE 15 /* SCSI disks - not a hard limit */
+#define HRDISK_TYPE_SHIFT 4 /* log2 (MAX_DISKS_PER_TYPE+1) */
+
+typedef struct {
+ const char *disk_devpart_string; /* printf() format disk part. name */
+ short disk_controller; /* controller id or -1 if NA */
+ short disk_device_first; /* first device id */
+ short disk_device_last; /* last device id */
+ const char *disk_devfull_string; /* printf() format full disk name */
+ short disk_partition_first; /* first partition id */
+ short disk_partition_last; /* last partition id */
+} HRD_disk_t;
+
+static HRD_disk_t disk_devices[MAX_NUMBER_DISK_TYPES];
+static int HR_number_disk_types = 0;
+
+static void
+Add_HR_Disk_entry(const char *devpart_string,
+ int first_ctl,
+ int last_ctl,
+ int first_dev,
+ int last_dev,
+ const char *devfull_string,
+ int first_partn, int last_partn)
+{
+ int lodev, hidev, nbr_created = 0;
+
+ while (first_ctl <= last_ctl) {
+ for (lodev = first_dev;
+ lodev < last_dev && MAX_NUMBER_DISK_TYPES > HR_number_disk_types;
+ lodev += (1+MAX_DISKS_PER_TYPE), HR_number_disk_types++)
+ {
+ nbr_created++;
+ /*
+ * Split long runs of disks into separate "types"
+ */
+ hidev = lodev + MAX_DISKS_PER_TYPE;
+ if (last_dev < hidev)
+ hidev = last_dev;
+ disk_devices[HR_number_disk_types].disk_devpart_string =
+ devpart_string;
+ disk_devices[HR_number_disk_types].disk_controller = first_ctl;
+ disk_devices[HR_number_disk_types].disk_device_first = lodev;
+ disk_devices[HR_number_disk_types].disk_device_last = hidev;
+ disk_devices[HR_number_disk_types].disk_devfull_string =
+ devfull_string;
+ disk_devices[HR_number_disk_types].disk_partition_first =
+ first_partn;
+ disk_devices[HR_number_disk_types].disk_partition_last =
+ last_partn;
+#if DEBUG_TEST
+ DEBUGMSGTL(("host/hr_disk",
+ "Add_HR %02d '%s' first=%d last=%d\n",
+ HR_number_disk_types, devpart_string, lodev, hidev));
+#endif
+ }
+ first_ctl++;
+ }
+
+ if (nbr_created == 0 || MAX_NUMBER_DISK_TYPES < HR_number_disk_types) {
+ HR_number_disk_types = MAX_NUMBER_DISK_TYPES;
+ DEBUGMSGTL(("host/hr_disk",
+ "WARNING! Add_HR_Disk_entry '%s' incomplete, %d created\n",
+ devpart_string, nbr_created));
+ }
+#if DEBUG_TEST
+ else
+ DEBUGMSGTL(("host/hr_disk",
+ "Add_HR_Disk_entry '%s' completed, %d created\n",
+ devpart_string, nbr_created));
+#endif
+}
+
+void
+Init_HR_Disk(void)
+{
+ HRD_type_index = 0;
+ HRD_index = -1;
+ DEBUGMSGTL(("host/hr_disk", "Init_Disk\n"));
+}
+
+int
+Get_Next_HR_Disk(void)
+{
+ char string[1024];
+ int fd, result;
+ int iindex;
+ int max_disks;
+ time_t now;
+
+ HRD_index++;
+ (void *) time(&now);
+ DEBUGMSGTL(("host/hr_disk", "Next_Disk type %d of %d\n",
+ HRD_type_index, HR_number_disk_types));
+ while (HRD_type_index < HR_number_disk_types) {
+ max_disks = disk_devices[HRD_type_index].disk_device_last -
+ disk_devices[HRD_type_index].disk_device_first + 1;
+ DEBUGMSGTL(("host/hr_disk", "Next_Disk max %d of type %d\n",
+ max_disks, HRD_type_index));
+
+ while (HRD_index < max_disks) {
+ iindex = (HRD_type_index << HRDISK_TYPE_SHIFT) + HRD_index;
+
+ /*
+ * Check to see whether this device
+ * has been probed for 'recently'
+ * and skip if so.
+ * This has a *major* impact on run
+ * times (by a factor of 10!)
+ */
+ if ((HRD_history[iindex] > 0) &&
+ ((now - HRD_history[iindex]) < 60)) {
+ HRD_index++;
+ continue;
+ }
+
+ /*
+ * Construct the full device name in "string"
+ */
+ if (disk_devices[HRD_type_index].disk_controller != -1) {
+ snprintf(string, sizeof(string)-1,
+ disk_devices[HRD_type_index].disk_devfull_string,
+ disk_devices[HRD_type_index].disk_controller,
+ disk_devices[HRD_type_index].disk_device_first +
+ HRD_index);
+ } else {
+ snprintf(string, sizeof(string)-1,
+ disk_devices[HRD_type_index].disk_devfull_string,
+ disk_devices[HRD_type_index].disk_device_first +
+ HRD_index);
+ }
+ string[ sizeof(string)-1 ] = 0;
+
+ DEBUGMSGTL(("host/hr_disk", "Get_Next_HR_Disk: %s (%d/%d)\n",
+ string, HRD_type_index, HRD_index));
+
+ if (HRD_history[iindex] == -1) {
+ /*
+ * check whether this device is in the "ignoredisk" list in
+ * the config file. if yes this device will be marked as
+ * invalid for the future, i.e. it won't ever be checked
+ * again.
+ */
+ if (match_disk_config(string)) {
+ /*
+ * device name matches entry in ignoredisk list
+ */
+ DEBUGMSGTL(("host/hr_disk",
+ "Get_Next_HR_Disk: %s ignored\n", string));
+ HRD_history[iindex] = LONG_MAX;
+ HRD_index++;
+ continue;
+ }
+ }
+
+ /*
+ * use O_NDELAY to avoid CDROM spin-up and media detection
+ * * (too slow) --okir
+ */
+ /*
+ * at least with HP-UX 11.0 this doesn't seem to work properly
+ * * when accessing an empty CDROM device --jsf
+ */
+#ifdef O_NDELAY /* I'm sure everything has it, but just in case... --Wes */
+ fd = open(string, O_RDONLY | O_NDELAY);
+#else
+ fd = open(string, O_RDONLY);
+#endif
+ if (fd != -1) {
+ result = Query_Disk(fd, string);
+ close(fd);
+ if (result != -1) {
+ HRD_history[iindex] = 0;
+ return ((HRDEV_DISK << HRDEV_TYPE_SHIFT) + iindex);
+ }
+ }
+ HRD_history[iindex] = now;
+ HRD_index++;
+ }
+ HRD_type_index++;
+ HRD_index = 0;
+ }
+ HRD_index = -1;
+ return -1;
+}
+
+int
+Get_Next_HR_Disk_Partition(char *string, size_t str_len, int HRP_index)
+{
+ DEBUGMSGTL(("host/hr_disk", "Next_Partition type %d/%d:%d\n",
+ HRD_type_index, HRD_index, HRP_index));
+
+ /*
+ * no more partition names => return -1
+ */
+ if (disk_devices[HRD_type_index].disk_partition_last -
+ disk_devices[HRD_type_index].disk_partition_first + 1
+ <= HRP_index) {
+ return -1;
+ }
+
+ /*
+ * Construct the partition name in "string"
+ */
+ if (disk_devices[HRD_type_index].disk_controller != -1) {
+ snprintf(string, str_len-1,
+ disk_devices[HRD_type_index].disk_devpart_string,
+ disk_devices[HRD_type_index].disk_controller,
+ disk_devices[HRD_type_index].disk_device_first + HRD_index,
+ disk_devices[HRD_type_index].disk_partition_first +
+ HRP_index);
+ } else {
+ snprintf(string, str_len-1,
+ disk_devices[HRD_type_index].disk_devpart_string,
+ disk_devices[HRD_type_index].disk_device_first + HRD_index,
+ disk_devices[HRD_type_index].disk_partition_first +
+ HRP_index);
+ }
+ string[ str_len-1 ] = 0;
+
+ DEBUGMSGTL(("host/hr_disk",
+ "Get_Next_HR_Disk_Partition: %s (%d/%d:%d)\n", string,
+ HRD_type_index, HRD_index, HRP_index));
+
+ return 0;
+}
+
+static void
+Save_HR_Disk_Specific(void)
+{
+#ifdef DIOC_DESCRIBE
+ HRD_savedIntf_type = HRD_info.intf_type;
+ HRD_savedDev_type = HRD_info.dev_type;
+ HRD_savedFlags = HRD_info.flags;
+ HRD_savedCapacity = HRD_cap.lba / 2;
+#endif
+#ifdef DKIOCINFO
+ HRD_savedCtrl_type = HRD_info.dki_ctype;
+ HRD_savedFlags = HRD_info.dki_flags;
+ HRD_savedCapacity = HRD_cap.dkg_ncyl * HRD_cap.dkg_nhead * HRD_cap.dkg_nsect / 2; /* ??? */
+#endif
+#ifdef HAVE_LINUX_HDREG_H
+ HRD_savedCapacity = HRD_info.lba_capacity / 2;
+ HRD_savedFlags = HRD_info.config;
+#endif
+#ifdef DIOCGDINFO
+ HRD_savedCapacity = HRD_info.d_secperunit / 2;
+#endif
+}
+
+static void
+Save_HR_Disk_General(void)
+{
+#ifdef DIOC_DESCRIBE
+ strncpy(HRD_savedModel, HRD_info.model_num, sizeof(HRD_savedModel)-1);
+ HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
+#endif
+#ifdef DKIOCINFO
+ strncpy(HRD_savedModel, HRD_info.dki_dname, sizeof(HRD_savedModel)-1);
+ HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
+#endif
+#ifdef HAVE_LINUX_HDREG_H
+ strncpy(HRD_savedModel, (const char *) HRD_info.model,
+ sizeof(HRD_savedModel)-1);
+ HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
+#endif
+#ifdef DIOCGDINFO
+ strncpy(HRD_savedModel, dktypenames[HRD_info.d_type],
+ sizeof(HRD_savedModel)-1);
+ HRD_savedModel[ sizeof(HRD_savedModel)-1 ] = 0;
+#endif
+}
+
+static const char *
+describe_disk(int idx)
+{
+ if (HRD_savedModel[0] == '\0')
+ return ("some sort of disk");
+ else
+ return (HRD_savedModel);
+}
+
+
+static int
+Query_Disk(int fd, const char *devfull)
+{
+ int result = -1;
+
+#ifdef DIOC_DESCRIBE
+ result = ioctl(fd, DIOC_DESCRIBE, &HRD_info);
+ if (result != -1)
+ result = ioctl(fd, DIOC_CAPACITY, &HRD_cap);
+#endif
+
+#ifdef DKIOCINFO
+ result = ioctl(fd, DKIOCINFO, &HRD_info);
+ if (result != -1)
+ result = ioctl(fd, DKIOCGGEOM, &HRD_cap);
+#endif
+
+#ifdef HAVE_LINUX_HDREG_H
+ if (HRD_type_index == 0) /* IDE hard disk */
+ result = ioctl(fd, HDIO_GET_IDENTITY, &HRD_info);
+ else if (HRD_type_index <= 2) { /* SCSI hard disk and md devices */
+ long h;
+ result = ioctl(fd, BLKGETSIZE, &h);
+ if (result != -1 && HRD_type_index == 2 && h == 0L)
+ result = -1; /* ignore empty md devices */
+ if (result != -1) {
+ HRD_info.lba_capacity = h;
+ if (HRD_type_index == 1)
+ snprintf( HRD_info.model, sizeof(HRD_info.model)-1,
+ "SCSI disk (%s)", devfull);
+ else
+ snprintf( HRD_info.model, sizeof(HRD_info.model)-1,
+ "RAID disk (%s)", devfull);
+ HRD_info.model[ sizeof(HRD_info.model)-1 ] = 0;
+ HRD_info.config = 0;
+ }
+ }
+#endif
+
+#ifdef DIOCGDINFO
+ result = ioctl(fd, DIOCGDINFO, &HRD_info);
+#endif
+
+ return (result);
+}
+
+
+static int
+Is_It_Writeable(void)
+{
+#ifdef DIOC_DESCRIBE
+ if ((HRD_savedFlags & WRITE_PROTECT_FLAG) ||
+ (HRD_savedDev_type == CDROM_DEV_TYPE))
+ return (2); /* read only */
+#endif
+
+#ifdef DKIOCINFO
+ if (HRD_savedCtrl_type == DKC_CDROM)
+ return (2); /* read only */
+#endif
+
+ return (1); /* read-write */
+}
+
+static int
+What_Type_Disk(void)
+{
+#ifdef DIOC_DESCRIBE
+ switch (HRD_savedDev_type) {
+ case DISK_DEV_TYPE:
+ if (HRD_savedIntf_type == PC_FDC_INTF)
+ return (4); /* Floppy Disk */
+ else
+ return (3); /* Hard Disk */
+ break;
+ case CDROM_DEV_TYPE:
+ return (5); /* Optical RO */
+ break;
+ case WORM_DEV_TYPE:
+ return (6); /* Optical WORM */
+ break;
+ case MO_DEV_TYPE:
+ return (7); /* Optical R/W */
+ break;
+ default:
+ return (2); /* Unknown */
+ break;
+ }
+#endif
+
+#ifdef DKIOCINFO
+ switch (HRD_savedCtrl_type) {
+ case DKC_WDC2880:
+ case DKC_DSD5215:
+#ifdef DKC_XY450
+ case DKC_XY450:
+#endif
+ case DKC_ACB4000:
+ case DKC_MD21:
+#ifdef DKC_XD7053
+ case DKC_XD7053:
+#endif
+ case DKC_SCSI_CCS:
+#ifdef DKC_PANTHER
+ case DKC_PANTHER:
+#endif
+#ifdef DKC_CDC_9057
+ case DKC_CDC_9057:
+#endif
+#ifdef DKC_FJ_M1060
+ case DKC_FJ_M1060:
+#endif
+ case DKC_DIRECT:
+ case DKC_PCMCIA_ATA:
+ return (3); /* Hard Disk */
+ break;
+ case DKC_NCRFLOPPY:
+ case DKC_SMSFLOPPY:
+ case DKC_INTEL82077:
+ return (4); /* Floppy Disk */
+ break;
+ case DKC_CDROM:
+ return (5); /* Optical RO */
+ break;
+ case DKC_PCMCIA_MEM:
+ return (8); /* RAM disk */
+ break;
+ case DKC_MD: /* "meta-disk" driver */
+ return (1); /* Other */
+ break;
+ }
+#endif
+
+
+ return (2); /* Unknown */
+}
+
+static int
+Is_It_Removeable(void)
+{
+#ifdef DIOC_DESCRIBE
+ if ((HRD_savedIntf_type == PC_FDC_INTF) ||
+ (HRD_savedDev_type == WORM_DEV_TYPE) ||
+ (HRD_savedDev_type == MO_DEV_TYPE) ||
+ (HRD_savedDev_type == CDROM_DEV_TYPE))
+ return (1); /* true */
+#endif
+
+#ifdef DKIOCINFO
+ if ((HRD_savedCtrl_type == DKC_CDROM) ||
+ (HRD_savedCtrl_type == DKC_NCRFLOPPY) ||
+ (HRD_savedCtrl_type == DKC_SMSFLOPPY) ||
+ (HRD_savedCtrl_type == DKC_INTEL82077) ||
+ (HRD_savedCtrl_type == DKC_PCMCIA_MEM) ||
+ (HRD_savedCtrl_type == DKC_PCMCIA_ATA))
+ return (1); /* true */
+#endif
+
+#ifdef HAVE_LINUX_HDREG_H
+ if (HRD_savedFlags & 0x80)
+ return (1); /* true */
+#endif
+
+ return (2); /* false */
+}