Hello All,

Since upstream seams to be no longer active on this one I went ahead and did 
some maintenance work on arrayprobe.

I don't use arrayprobe and looked at it because it is RC for Squeeze so please 
review (it's not one-liner) and (if brave enough:) test it.

Instead of just fix reported issue with tape I refactored some code to not used 
dynamic memory, I hope this fix memory issues reported already and minimize 
chance of similar bugs in the future.  It also fixes some other bugs identified 
during reviewing/coding (overwriting memory, leaks etc) and buffer overflow 
bugs 
reported.

As I mentioned before, I'm not able to test it myself so there might be (I'm 
pretty sure of that :>) some bugs.
I can spend some more time on it if testers show up and report issues :)

Comments are welcome.

-- 
Szymon K. Janc
szy...@janc.net.pl // GG: 1383435
--- probe.c_orig	2011-01-18 00:33:37.817369726 +0100
+++ probe.c	2011-01-18 01:06:02.517370069 +0100
@@ -43,16 +43,16 @@
 #include "config.h"
 
 typedef struct _logdrv_state {
-  int state;
-  char *message;
-  int severity;
+	int state;
+	const char *message;
+	int severity;
 } logdrv_state;
 
 typedef struct _logdrv {
-  char *devicestr;  /* filesystem device node eg. /dev/cciss/c0d0 */
-  int type; /* type of controller eg. CCISS or IDA */
-  int drvnum; /* number of this logical drive */
-  logdrv_state state; /* current state of this logical drive */
+	char *devicestr;	/* filesystem device node eg. /dev/cciss/c0d0 */
+	int type;		/* type of controller eg. CCISS or IDA */
+	int drvnum;		/* number of this logical drive */
+	logdrv_state state;	/* current state of this logical drive */
 } logdrv;
 
 /* globals */
@@ -65,53 +65,38 @@ int verbose = 0;
 /* defines */
 #define CTTYPE_CCISS 1
 #define CTTYPE_IDA 2
+#define MAX_LOGICAL_DRIVES 64
 
-int
-cciss_get_event (int device_fd, int reset_pointer, cciss_event_type * event)
+void allocation_failed(void)
 {
-  int result;
+	printf("WARNING Arrayprobe cannot allocate enough memory. Aborting.\n");
+	exit(1);
+}
+
+int cciss_get_event(int device_fd, int reset_pointer, cciss_event_type * event)
+{
+	int result;
 	IOCTL_Command_struct iocommand;
-	unsigned char *buffer;
+	unsigned char buffer[512] = {0};
 
-	iocommand.LUN_info.LunAddrBytes[0] = 0;
-	iocommand.LUN_info.LunAddrBytes[1] = 0;
-	iocommand.LUN_info.LunAddrBytes[2] = 0;
-	iocommand.LUN_info.LunAddrBytes[3] = 0;
-	iocommand.LUN_info.LunAddrBytes[4] = 0;
-	iocommand.LUN_info.LunAddrBytes[5] = 0;
-	iocommand.LUN_info.LunAddrBytes[6] = 0;
-	iocommand.LUN_info.LunAddrBytes[7] = 0;
+	memset(&iocommand, 0, sizeof(iocommand));
 
 	iocommand.Request.Type.Type = TYPE_CMD;
 	iocommand.Request.Type.Attribute = ATTR_SIMPLE;
 	iocommand.Request.Type.Direction = XFER_READ;
 
-	iocommand.Request.Timeout = 0;	/* don't time out */
-
 	iocommand.Request.CDBLen = 13;
 	iocommand.Request.CDB[0] = 0xC0;	/* CISS Read */
 	iocommand.Request.CDB[1] = 0xD0;	/* Notify on Event */
-	iocommand.Request.CDB[2] = 0x0;	/* reserved, leave 0 */
-	iocommand.Request.CDB[3] = 0x0;	/* reserved, leave 0 */
-	iocommand.Request.CDB[4] = 0x0;
-	iocommand.Request.CDB[5] = 0x0;
-	iocommand.Request.CDB[6] = 0x0;
 	iocommand.Request.CDB[7] = (reset_pointer) ? 0x7 : 0x3;	/* bit 2 set = reset pointer, bit 0 set = synchronous mode */
-	iocommand.Request.CDB[8] = 0x0;
-	iocommand.Request.CDB[9] = 0x0;
 	iocommand.Request.CDB[10] = 0x2;
-	iocommand.Request.CDB[11] = 0x0;
-	iocommand.Request.CDB[12] = 0x0;
 
-	buffer = (unsigned char *) malloc (512);
-	memset (buffer, 0x0, 512);
 	iocommand.buf_size = 512;
 	iocommand.buf = buffer;
 
-	result = ioctl (device_fd, CCISS_PASSTHRU, &iocommand);
-	if (result < 0)
-	{
-		perror (" * ioctl failed");
+	result = ioctl(device_fd, CCISS_PASSTHRU, &iocommand);
+	if (result < 0) {
+		perror(" * ioctl failed");
 		return -1;
 	}
 
@@ -119,60 +104,41 @@ cciss_get_event (int device_fd, int rese
 	 * overrun (1) should not happen anyway and
 	 * underrun (2) is not a problem
 	 */
-	if ((iocommand.error_info.CommandStatus != 1) && (iocommand.error_info.CommandStatus != 2) && (iocommand.error_info.CommandStatus != 0)) {
-	  printf (" * Command failed with Comnmand Status %d\n", iocommand.error_info.CommandStatus);
-	  return -1;
+	if (iocommand.error_info.CommandStatus > 2) {
+		printf(" * Command failed with Command Status %u\n",
+				iocommand.error_info.CommandStatus);
+		return -1;
 	}
 
-	memcpy (event, buffer, 512);
+	memcpy(event, buffer, 512);
 	return 0;
 }
 
-int
-cciss_get_logical_luns (int device_fd, cciss_report_logicallun_struct * logluns)
+int cciss_get_logical_luns(int device_fd,
+				cciss_report_logicallun_struct * logluns)
 {
-  int result;
 	IOCTL_Command_struct iocommand;
-	unsigned char *buffer;
+	unsigned char buffer[128] = {0};
 
-	iocommand.LUN_info.LunAddrBytes[0] = 0;
-	iocommand.LUN_info.LunAddrBytes[1] = 0;
-	iocommand.LUN_info.LunAddrBytes[2] = 0;
-	iocommand.LUN_info.LunAddrBytes[3] = 0;
-	iocommand.LUN_info.LunAddrBytes[4] = 0;
-	iocommand.LUN_info.LunAddrBytes[5] = 0;
-	iocommand.LUN_info.LunAddrBytes[6] = 0;
-	iocommand.LUN_info.LunAddrBytes[7] = 0;
+	memset(&iocommand, 0, sizeof(iocommand));
 
 	iocommand.Request.Type.Type = TYPE_CMD;
 	iocommand.Request.Type.Attribute = ATTR_SIMPLE;
 	iocommand.Request.Type.Direction = XFER_READ;
 
-	iocommand.Request.Timeout = 0;	/* don't time out */
-
 	iocommand.Request.CDBLen = 12;
-	iocommand.Request.CDB[0] = 0xC2; /* Report logical LUNs */
-	iocommand.Request.CDB[1] = 0x0;	 /* reserved, leave 0 */
-	iocommand.Request.CDB[2] = 0x0;	 /* reserved, leave 0 */
-	iocommand.Request.CDB[3] = 0x0;	 /* reserved, leave 0 */
-	iocommand.Request.CDB[4] = 0x0;  /* reserved, leave 0 */
-	iocommand.Request.CDB[5] = 0x0;  /* reserved, leave 0 */
-	iocommand.Request.CDB[6] = 0x0;  /* byte 6-9 alloc length = 128 (0x80)*/
+	iocommand.Request.CDB[0] = 0xC2;	/* Report logical LUNs */
+
+	iocommand.Request.CDB[6] = 0x0;	/* byte 6-9 alloc length = 128 (0x80) */
 	iocommand.Request.CDB[7] = 0x0;
 	iocommand.Request.CDB[8] = 0x0;
 	iocommand.Request.CDB[9] = 0x80;
-	iocommand.Request.CDB[10] = 0x0; /* reserved, leave 0 */
-	iocommand.Request.CDB[11] = 0x0; /* control ? */
 
-	buffer = (unsigned char *) malloc (128);
-	memset (buffer, 0x0, 128);
 	iocommand.buf_size = 128;
 	iocommand.buf = buffer;
 
-	result = ioctl (device_fd, CCISS_PASSTHRU, &iocommand);
-	if (result < 0)
-	{
-		perror (" * ioctl failed");
+	if (ioctl(device_fd, CCISS_PASSTHRU, &iocommand) < 0) {
+		perror(" * ioctl failed");
 		return -1;
 	}
 
@@ -180,64 +146,56 @@ cciss_get_logical_luns (int device_fd, c
 	 * overrun (1) should not happen anyway and
 	 * underrun (2) is not a problem
 	 */
-	if ((iocommand.error_info.CommandStatus != 1) && (iocommand.error_info.CommandStatus != 2) && (iocommand.error_info.CommandStatus != 0)) {
-	  printf (" * Command failed with Comnmand Status %d\n", iocommand.error_info.CommandStatus);
-	  return -1;
+	if (iocommand.error_info.CommandStatus > 2) {
+		printf(" * Command failed with Command Status %d\n",
+				iocommand.error_info.CommandStatus);
+		return -1;
 	}
-	
- 	memcpy (logluns, buffer, 128);
+
+	memcpy(logluns, buffer, 128);
 	return 0;
 }
 
-int
-cciss_simulate_get_event (int device_fd, int reset_pointer,
-			  cciss_event_type * event)
+int cciss_simulate_get_event(int device_fd, int reset_pointer,
+						cciss_event_type * event)
 {
-	unsigned char *buffer;
+	unsigned char buffer[512];
 
-	buffer = (unsigned char *) malloc (512);
-	if ((read (device_fd, buffer, 512)) < 0)
-	{
-		perror ("reading from file");
+	if ((read(device_fd, buffer, 512)) < 0) {
+		perror("reading from file");
 		return -1;
 	}
-	memcpy (event, buffer, 512);
+	memcpy(event, buffer, 512);
 	return 0;
 }
 
-void
-cciss_print_event (cciss_event_type event)
+void cciss_print_event(cciss_event_type event)
 {
 	int prevstate, newstate;
-	
-	printf ("Event code %d/%d/%d",
-		event.class.class, event.class.subclass, event.class.detail);
-	if (event.tag == 0)
-	{
-		printf ("\n");
-	}
-	else
-	{
-		printf (" with tag %d\n", event.tag);
-	}
-
-	if (event.time.month != 0)
-	{
-		printf ("at %d-%d-%d %02d:%02d:%02d\n",
-			event.time.day, 
-			event.time.month, 
+
+	printf("Event code %u/%u/%u", event.class.class, event.class.subclass,
+							event.class.detail);
+
+	if (event.tag != 0)
+		printf(" with tag %u", event.tag);
+
+	printf("\n");
+
+	if (event.time.month != 0) {
+		printf("at %u-%u-%u %02u:%02u:%02u\n",
+			event.time.day,
+			event.time.month,
 			event.time.year,
 			event.time.seconds / 3600,
 			event.time.seconds % 3600 / 60,
 			event.time.seconds % 60);
-	}
-	else if (event.timestamp != 0)
-	{
-		printf ("at %d seconds since last power cycle or controler reset\n", event.timestamp);
+	} else if (event.timestamp != 0) {
+		printf("at %u seconds since last power cycle or controller reset\n",
+			event.timestamp);
 	}
 
-	printf ("with message: %s\n", event.mesgstring);
-	
+	printf("with message: %s\n", event.mesgstring);
+
 /* 	printf ("on device %02X %02X %02X %02X %02X %02X %02X %02X\n",
  * 			event.deviceaddr.LunAddrBytes[0],
  * 			event.deviceaddr.LunAddrBytes[1],
@@ -248,57 +206,50 @@ cciss_print_event (cciss_event_type even
  * 			event.deviceaddr.LunAddrBytes[6],
  * 			event.deviceaddr.LunAddrBytes[7]);
  */
-	
 
-	if (CompareEvent(event, 5,0,0)) {	
+	if (CompareEvent(event, 5, 0, 0)) {
 		prevstate = event.detail.logstatchange.previouslogicaldrivestate;
 		newstate = event.detail.logstatchange.newlogicaldrivestate;
-		printf ("logical drive %d, changed from state %d to %d\n",
-		        event.detail.logstatchange.logicaldrivenumber,
-				prevstate,
-				newstate);
-		printf ("state %d: %s\n", 
-				prevstate,
-				logicaldrivestatusstr[prevstate]);
-		printf ("state %d: %s\n", 
-				newstate,
-				logicaldrivestatusstr[newstate]);
-	}
-	else if (CompareEvent(event, 4,0,0)) {
-		printf ("physical drive %d has failed with failurecode %d.\n",
+
+		printf("logical drive %u, changed from state %d to %d\n",
+				event.detail.logstatchange.logicaldrivenumber,
+				prevstate, newstate);
+		printf("state %u: %s\n", prevstate, logicaldrivestatusstr[prevstate]);
+		printf("state %u: %s\n", newstate, logicaldrivestatusstr[newstate]);
+	} else if (CompareEvent(event, 4, 0, 0)) {
+		printf("physical drive %u has failed with failure code %u.\n",
 				event.detail.phystatchange.physicaldrivenumber,
 				event.detail.phystatchange.failurereason);
-		if (event.detail.phystatchange.configureddriveflag != 0) {
+
+		if (event.detail.phystatchange.configureddriveflag != 0)
 			printf("this drive is part of a logical drive\n");
-		}
-		if (event.detail.phystatchange.sparedriveflag != 0) {
+
+		if (event.detail.phystatchange.sparedriveflag != 0)
 			printf ("this drive is a hot-spare for a logical drive\n");
-		}
-		
 	}
+
+	printf("\n");
 }
 
-int
-cciss_get_num_logicalluns(cciss_report_logicallun_struct logluns) {
-  int listlength = 0;
+int cciss_get_num_logicalluns(cciss_report_logicallun_struct logluns)
+{
+	int listlength = 0;
 
-  listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[0])) << 24;
-  listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[1])) << 16;
-  listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[2])) << 8;
-  listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[3]));
-  return listlength / 8;
-}
+	listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[0])) << 24;
+	listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[1])) << 16;
+	listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[2])) << 8;
+	listlength |= (0xff & (unsigned int)(logluns.LUNlist_len[3]));
 
-void
-cciss_print_logicalluns(cciss_report_logicallun_struct logluns) {
-  printf ("Number of logical volumes (%02X %02X %02X %02X) : %d\n", 
-	  logluns.LUNlist_len[0],
-	  logluns.LUNlist_len[1],
-	  logluns.LUNlist_len[2],
-	  logluns.LUNlist_len[3],
-	  cciss_get_num_logicalluns(logluns));
-}
+	listlength /= 8;
 
+	if (listlength > MAX_LOGICAL_DRIVES){
+		printf("maximum number of ida logical cciss exceeded. Limiting to %u (from %u)\n",
+		MAX_LOGICAL_DRIVES, listlength);
+		listlength = MAX_LOGICAL_DRIVES;
+	}
+
+	return listlength;
+}
 
 /* get the drivestates for logical drives attached to this controller
  * result:
@@ -306,291 +257,286 @@ cciss_print_logicalluns(cciss_report_log
  * 0 no logical drives detected
  * <0 error while trying to get states, see log message
  */
-int
-cciss_get_drivestates (char *device, logdrv *logdrvs, int maxlogdrvs)
+int cciss_get_drivestates(char *device, logdrv * logdrvs)
 {
-  int fd;
-  cciss_report_logicallun_struct logluns;
-  int num_logical_drives;
-  int counter;
-  int result;
-  cciss_event_type event;
-  int first_time;
-
-  fd = open(device, O_RDWR);
-  if (fd < 0) {
-    log ("failed to open device %s: %s\n", device, strerror(errno));
-    return -1;
-  }
-
-  log ("Retrieving logical drive information from controller %s\n", device);
-  if (cciss_get_logical_luns(fd, &logluns) < 0) {
-    log ("Retrieval of cciss logical lun data failed (%d)\n", result);
-    return -1;
-  }
-
-  if (verbose) {
-    cciss_print_logicalluns(logluns);
-  }
-  num_logical_drives = cciss_get_num_logicalluns(logluns);
-
-  log ("Controller %s reports %d logical drives\n", device, num_logical_drives);
-
-  for (counter = 0; counter < num_logical_drives; counter++) {
-    logdrvs[counter].devicestr = (char *)malloc(strlen(device)+1);
-    strcpy(logdrvs[counter].devicestr, device);
-    logdrvs[counter].type = CTTYPE_CCISS;
-    logdrvs[counter].drvnum = counter;
-    logdrvs[counter].state.state = 0;
-    log ("Logical drive %d found on controller %s\n", counter, device);
-  }
-
-  first_time = 1;
-  do 
-    {
-      result = cciss_get_event (fd, first_time, &event);
-      if (CompareEvent(event, 5,0,0)) {
-	/* i'm only interested in logical drive state for now */
-	int drivenum = event.detail.logstatchange.logicaldrivenumber;
-	logdrvs[drivenum].state.state = event.detail.logstatchange.newlogicaldrivestate;
-	logdrvs[drivenum].state.severity = logicaldrivestatusseverity[event.detail.logstatchange.newlogicaldrivestate];
-	logdrvs[drivenum].state.message = (char *)malloc(strlen(logicaldrivestatusstr[event.detail.logstatchange.newlogicaldrivestate] + 1));
-	strcpy (logdrvs[drivenum].state.message, logicaldrivestatusstr[event.detail.logstatchange.newlogicaldrivestate]);
-      }
-      if (verbose) {
-	cciss_print_event (event);
-	printf ("\n");
-      }
-      first_time = 0;
-    }
-  while (event.class.class != 0);
-
-  return num_logical_drives;
-}
-
-int
-ida_get_num_logicalluns (int devicefd)
-{
-  ida_ioctl_t io;
-  char buffer[30];
-  int cntr;
-
-
-  /* clear io */
-  memset (&io, 0, sizeof (io));
-
-  io.cmd = ID_CTLR;
-
-  if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
-    {
-      log ("Error in ida ioctl: %s\n", strerror(errno)); 
-      return -1;
-    }
-
-  //boardid2str (io.c.id_ctlr.board_id, buffer);
-
-  return io.c.id_ctlr.nr_drvs;
-}
-
-int
-ida_get_drivestate(int devicefd, int logicaldrv)
-{
-  ida_ioctl_t io;
-  ida_ioctl_t io2;
-  int nr_blks, blks_tr;
-
-  memset (&io, 0, sizeof (io));
-
-  io.cmd = ID_LOG_DRV;
-  io.unit = logicaldrv | UNITVALID;
-
-  if (ioctl (devicefd, IDAPASSTHRU, &io) < 0)
-    {
-      log ("FATAL: ID_LOG_DRV ioctl failed: %s", strerror(errno));
-      return -1;
-    }
-
-  memset (&io2, 0, sizeof (io2));
-
-  io2.cmd = SENSE_LOG_DRV_STAT;
-  io2.unit = logicaldrv | UNITVALID;
-
-  if (ioctl (devicefd, IDAPASSTHRU, &io2) < 0)
-    {
-      log ("FATAL: SENSE_LOG_DRV_STAT ioctl failed: %s", strerror(errno));
-      return -1;
-    }
-
-  return io2.c.sense_log_drv_stat.status;
-}
-
-int
-ida_get_drivestates (char *device, logdrv *logdrvs, int maxlogdrvs)
-{
-  int fd;
-  int num_logical_drives;
-  int counter;
-  int result;
-
-  fd = open(device, O_RDWR);
-  if (fd < 0) {
-    log ("failed to open device %s: %s\n", device, strerror(errno));
-    return -1;
-  }
-
-  num_logical_drives = ida_get_num_logicalluns(fd);
-  if (num_logical_drives < 0) {
-    log ("ioctl failed to retrieve number of logical drives\n", NULL);
-    return -1;
-  }
-
-  for (counter = 0; counter < num_logical_drives; counter++) {
-    result = ida_get_drivestate (fd, counter);
-    if (result < 0) {
-      log ("Error while retrieving state information (%d)\n", result);
-      result = 0; /* we should set this to a critical state */
-    }
-    logdrvs[counter].devicestr = (char *)malloc(strlen(device)+1);
-    strcpy(logdrvs[counter].devicestr, device);
-    logdrvs[counter].type = CTTYPE_IDA;
-    logdrvs[counter].drvnum = counter;
-    logdrvs[counter].state.state = result;
-    logdrvs[counter].state.severity = logicaldrivestatusseverity[result];
-    logdrvs[counter].state.message = (char *)malloc(strlen(logicaldrivestatusstr[result] + 1));
-    strcpy(logdrvs[counter].state.message, logicaldrivestatusstr[result]);
-    log ("Logical drive %d found on controller %s\n", counter, device);
-  }
+	int fd;
+	cciss_report_logicallun_struct logluns;
+	int num_logical_drives;
+	int counter;
+	int result;
+	cciss_event_type event;
+	int first_time;
+
+	fd = open(device, O_RDWR);
+	if (fd < 0) {
+		log("failed to open device %s: %s\n", device, strerror(errno));
+		return -1;
+	}
+
+	log("Retrieving logical drive information from controller %s\n", device);
+
+	if (cciss_get_logical_luns(fd, &logluns) < 0) {
+		log("Retrieval of cciss logical lun data failed (%s)\n", device);
+		close(fd);
+		return -1;
+	}
+
+	num_logical_drives = cciss_get_num_logicalluns(logluns);
+
+	log("Number of logical volumes (%02X %02X %02X %02X) : %d\n",
+			logluns.LUNlist_len[0], logluns.LUNlist_len[1],
+			logluns.LUNlist_len[2], logluns.LUNlist_len[3],
+			num_logical_drives);
 
-  return num_logical_drives;
-} 
+	log("Controller %s reports %d logical drives\n", device, num_logical_drives);
+
+	for (counter = 0; counter < num_logical_drives; counter++) {
+		logdrvs[counter].devicestr = malloc(strlen(device) + 1);
+		if (! logdrvs[counter].devicestr)
+			allocation_failed();
+
+		strcpy(logdrvs[counter].devicestr, device);
+
+		logdrvs[counter].type = CTTYPE_CCISS;
+		logdrvs[counter].drvnum = counter;
+		logdrvs[counter].state.state = 0;
+
+		log("Logical drive %d found on controller %s\n", counter, device);
+	}
+
+	first_time = 1;
+	do {
+		if (cciss_get_event(fd, first_time, &event) < 0) {
+			log("Retrieval of cciss event failed (%s)\n", device);
+			close(fd);
+			return -1;
+		}
+
+		if (CompareEvent(event, 5, 0, 0)) {
+			/* i'm only interested in logical drive state for now */
+			int drivenum = event.detail.logstatchange.logicaldrivenumber;
+			logdrvs[drivenum].state.state = event.detail.logstatchange.newlogicaldrivestate;
+			logdrvs[drivenum].state.severity = logicaldrivestatusseverity[event.detail.logstatchange.newlogicaldrivestate];
+			logdrvs[drivenum].state.message = logicaldrivestatusstr[event.detail. logstatchange.newlogicaldrivestate];
+		}
+		if (verbose)
+			cciss_print_event(event);
+
+		first_time = 0;
+	}
+	while (event.class.class != 0);
+
+	close(fd);
+	return num_logical_drives;
+}
 
-int
-main (int argc, char *argv[])
+int ida_get_num_logicalluns(int devicefd)
 {
-	cciss_event_type event;
-	logdrv_state *states;
-	int fd, option;
-	int simulate = 0;
+	ida_ioctl_t io;
+
+	/* clear io */
+	memset(&io, 0, sizeof(io));
+
+	io.cmd = ID_CTLR;
+
+	if (ioctl(devicefd, IDAPASSTHRU, &io) < 0) {
+		log("Error in ida ioctl: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if (io.c.id_ctlr.nr_drvs > MAX_LOGICAL_DRIVES) {
+		printf("maximum number of ida logical luns exceeded. Limiting to %u (from %u)\n",
+			MAX_LOGICAL_DRIVES, io.c.id_ctlr.nr_drvs);
+		return MAX_LOGICAL_DRIVES;
+	} else
+		return io.c.id_ctlr.nr_drvs;
+}
+
+int ida_get_drivestate(int devicefd, int logicaldrv)
+{
+	ida_ioctl_t io;
+
+	memset(&io, 0, sizeof(io));
+
+	io.cmd = ID_LOG_DRV;
+	io.unit = logicaldrv | UNITVALID;
+
+	if (ioctl(devicefd, IDAPASSTHRU, &io) < 0) {
+		log("FATAL: ID_LOG_DRV ioctl failed: %s", strerror(errno));
+		return -1;
+	}
+
+	memset(&io, 0, sizeof(io));
+
+	io.cmd = SENSE_LOG_DRV_STAT;
+	io.unit = logicaldrv | UNITVALID;
+
+	if (ioctl(devicefd, IDAPASSTHRU, &io) < 0) {
+		log("FATAL: SENSE_LOG_DRV_STAT ioctl failed: %s", strerror(errno));
+		return -1;
+	}
+
+	return io.c.sense_log_drv_stat.status;
+}
+
+int ida_get_drivestates(char *device, logdrv * logdrvs, int cur_logical)
+{
+	int fd;
+	int num_logical_drives;
+	int counter;
+	int result;
+
+	fd = open(device, O_RDWR);
+	if (fd < 0) {
+		log("failed to open device %s: %s\n", device, strerror(errno));
+		return -1;
+	}
+
+	num_logical_drives = ida_get_num_logicalluns(fd);
+	if (num_logical_drives < 0) {
+		log("ioctl failed to retrieve number of logical drives (%s)\n", device);
+		close(fd);
+		return -1;
+	}
+
+	for (counter = cur_logical; counter < num_logical_drives; counter++) {
+		result = ida_get_drivestate(fd, counter);
+		if (result < 0) {
+			log("Error while retrieving state information (%d)\n", result);
+			result = 0;	/* TODO we should set this to a critical state */
+		}
+
+		logdrvs[counter].devicestr = malloc(strlen(device) + 1);
+		if (! logdrvs[counter].devicestr)
+			allocation_failed();
+
+		strcpy(logdrvs[counter].devicestr, device);
+		logdrvs[counter].type = CTTYPE_IDA;
+		logdrvs[counter].drvnum = counter;
+		logdrvs[counter].state.state = result;
+		logdrvs[counter].state.severity = logicaldrivestatusseverity[result];
+		logdrvs[counter].state.message = logicaldrivestatusstr[result];
+
+		log("Logical drive %d found on controller %s\n", counter, device);
+	}
+
+	return num_logical_drives;
+}
+
+int main(int argc, char *argv[])
+{
+	int option;
 	char *filename = NULL;
 	int report_mode = 0;
 	int num_logical_drives = 0;
 	int reset_event_pointer = 1;
 	int result;
-	int ida_device = 0; /* only for use with -f , used to determine protocol to use */
-	int max_logical = 64; /* hardcoded */
-	int cur_logical = 0; /* number of drives detected */
-	logdrv *logdrvs = (logdrv *)malloc(sizeof(logdrv)*max_logical);
-	int worst_disk;
-        int worst_sev = SEV_NORMAL;
+	int ida_device = 0;	/* only for use with -f , used to determine protocol to use */
+	int cur_logical = 0;	/* number of drives detected */
+	logdrv logdrvs[MAX_LOGICAL_DRIVES] = {{0}};
+	int worst_disk = 0;
+	int worst_sev = SEV_NORMAL;
 	int cntr;
 
-	while ((option = getopt (argc, argv, "f:srhoi")) != EOF)
-	{
-		switch (option)
-		{
+	while ((option = getopt(argc, argv, "f:srhoi")) != EOF) {
+		switch (option) {
 		case 'f':
-			filename = (char *) malloc (strlen (optarg) + 1);
-			strncpy (filename, optarg, strlen (optarg) + 1);
-			break;
-		case 's':
-			simulate = 1;
+			filename = malloc(strlen(optarg) + 1);
+			if (! filename)
+				allocation_failed();
+
+			strncpy(filename, optarg, strlen(optarg) + 1);
 			break;
 		case 'r':
 			report_mode = 1;
 			verbose = 1;
 			break;
 		case 'o':
-		  reset_event_pointer = 0;
-		  break;
+			reset_event_pointer = 0;
+			break;
 		case 'i':
-		  ida_device = 1;
-		  break;
+			ida_device = 1;
+			break;
 		case 'h':
 		default:
-			printf ("Usage: ccissprobe [-f filename] [-s]\n");
-			printf (" -f <device>  : device to open\n");
-			/* printf (" -s             : simultion mode (use with -f)\n"); */
-			printf (" -r             : report (verbose) mode\n");
-			printf (" -o             : only read new events (since last run, CCISS devices only)\n");
-			printf (" -i             : force ida ioctls. (use with -f if the device is supported by the ida driver)\n");
-			exit (1);
+			printf("Usage: ccissprobe [-f filename] [-s]\n");
+			printf(" -f <device>  : device to open\n");
+			printf(" -r             : report (verbose) mode\n");
+			printf(" -o             : only read new events (since last run, CCISS devices only)\n");
+			printf(" -i             : force ida ioctls. (use with -f if the device is supported by the ida driver)\n");
+			exit(1);
 		}
 	}
 
-	/* prepare structures */
-	logdrvs = (logdrv *)malloc(sizeof(logdrv)*max_logical);
-
 	/* If a device is supplied on the commandline use that device,
 	 * otherwise scan for devices in all known places
 	 */
-	if (filename != NULL)
-	{
-	  if (ida_device) {
-	    result = ida_get_drivestates(filename, logdrvs, max_logical);
-	    if (result > 0) {
-	      cur_logical += result;
-	    }
-	  }
-	  else {
-	    result = cciss_get_drivestates(filename, logdrvs, max_logical);
-	    if (result > 0) {
-	      cur_logical += result;
-	    }
-	  }
-	}
-	else {
-	  /* if nothing is supplied on the commandline check the first cciss controller and the first ida controller */
-	  result = cciss_get_drivestates("/dev/cciss/c0d0", logdrvs, max_logical);
-	  if (result > 0) {
-	    cur_logical += result;
-	  }
-	  result = ida_get_drivestates("/dev/ida/c0d0", logdrvs, max_logical);
-	  if (result > 0) {
-	    cur_logical += result;
-	  }
+	if (filename != NULL) {
+		if (ida_device)
+			result = ida_get_drivestates(filename, logdrvs, 0);
+		else
+			result = cciss_get_drivestates(filename, logdrvs);
+
+		if (result > 0)
+			cur_logical = result;
+	} else {
+		/* if nothing is supplied on the commandline check the first cciss controller and the first ida controller */
+		result = cciss_get_drivestates("/dev/cciss/c0d0", logdrvs);
+		if (result > 0)
+			cur_logical = result;
+
+		result = ida_get_drivestates("/dev/ida/c0d0", logdrvs, cur_logical);
+		if (result > 0)
+			cur_logical += result;
 	}
 
 	if (cur_logical == 0) {
-	  /* no logical drives found, this is bad */
-	  printf ("CRITICAL no logical drives detected\n");
-	  return (2);
+		/* no logical drives found, this is bad */
+		printf("CRITICAL no logical drives detected\n");
+		return (2);
 	}
 
+	if ( cur_logical > MAX_LOGICAL_DRIVES) {
+		log("maximum number of logical cciss exceeded. Limiting to %u (from %u)\n",
+			MAX_LOGICAL_DRIVES, cur_logical);
+		cur_logical = MAX_LOGICAL_DRIVES;
+	}
+
+
+
 	/* Nagios part
 	 * nagios wants only one line with a status, so we print the worst situation we can find
 	 * and exit with a corresponding return code
-         */
+	 */
 	num_logical_drives = 0;
-	for (cntr = 0; cntr<cur_logical; cntr++) {
-	  if (logdrvs[cntr].state.state != 0) {
-	    if (logdrvs[cntr].state.severity > worst_sev) {
-	      worst_sev = logdrvs[cntr].state.severity;
-	      worst_disk = cntr;
-	    }
-	  }
-	  if (verbose) {
-	    printf ("Logical drive %d on controller %s has state %d\n", 
-		    logdrvs[cntr].drvnum, 
-		    logdrvs[cntr].devicestr, 
-		    logdrvs[cntr].state.state);
-	  }
+	for (cntr = 0; cntr < cur_logical; cntr++) {
+		if (logdrvs[cntr].state.state != 0) {
+			if (logdrvs[cntr].state.severity > worst_sev) {
+				worst_sev = logdrvs[cntr].state.severity;
+				worst_disk = cntr;
+			}
+		}
+
+		log("Logical drive %d on controller %s has state %d\n",
+			logdrvs[cntr].drvnum,
+			logdrvs[cntr].devicestr,
+			logdrvs[cntr].state.state);
 	}
 
 	if (worst_sev == SEV_CRITICAL) {
-	  printf ("CRITICAL Arrayprobe Logical drive %d on %s: %s\n", 
-		  logdrvs[worst_disk].drvnum, 
-		  logdrvs[worst_disk].devicestr, 
-		  logdrvs[worst_disk].state.message);
-	  return 2;
-	}
-	else if (worst_sev == SEV_WARNING) {
-	  printf ("WARNING Arrayprobe Logical drive %d on %s: %s\n", 
-		  logdrvs[worst_disk].drvnum,
-		  logdrvs[worst_disk].devicestr,
-		  logdrvs[worst_disk].state.message);
-	  return 1;
+		printf("CRITICAL Arrayprobe Logical drive %d on %s: %s\n",
+			logdrvs[worst_disk].drvnum,
+			logdrvs[worst_disk].devicestr,
+			logdrvs[worst_disk].state.message);
+		return 2;
+	} else if (worst_sev == SEV_WARNING) {
+		printf("WARNING Arrayprobe Logical drive %d on %s: %s\n",
+			logdrvs[worst_disk].drvnum,
+			logdrvs[worst_disk].devicestr,
+			logdrvs[worst_disk].state.message);
+		return 1;
 	}
 
-	printf ("OK Arrayprobe All controllers ok\n");
+	printf("OK Arrayprobe All controllers ok\n");
 	return 0;
 }

Reply via email to