RG337 RG337 - 1 month ago 8
C Question

scsi inquiry commands to get serial and model information

I have problems getting serial and model information from SCSI drives via an inquiry. My inquiry always returns empty strings.

Here is a quick and dirty code of the inquiry which should at least output the entire return of the inquiry. The output isn't formatted to really get specific information, but it should still work. But it doesn't.

#define DRIVEAMOUNT 20
#define MODELINQUIRY 0x12,0x00,0x00,0x00,0x4A,0x00 /* SCSI command for standard inquiry*/
#define SERIALINQUIRY 0x12,0x01,0x80,0x00,0x60,0x00 /* SCSI command for VPD inquiry page 0x80 for serial number */

/* used libraries */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
#include <inttypes.h>

/* send scsi command and recieve output, designed for use with *ONLY* an inquiry command but might work with more than only inquiry*/
int SCSI_sendcmd(uint64_t sg_fd, unsigned char *cmdblk, char *output) {
unsigned char reply_buffer[96];
sg_io_hdr_t io_hdr;
int i;

/* Send INQUIRY command */
memset(&io_hdr,0,sizeof(sg_io_hdr_t));
io_hdr.interface_id='S';
io_hdr.dxfer_direction=SG_DXFER_FROM_DEV;
io_hdr.dxfer_len=sizeof(reply_buffer);
io_hdr.dxferp=reply_buffer;
io_hdr.cmd_len=sizeof(cmdblk);
io_hdr.cmdp=cmdblk;
io_hdr.timeout=1000;

if (ioctl(sg_fd,SG_IO,&io_hdr)<0) {return 3;} /* cannot send inquiry command */

if ((io_hdr.info&SG_INFO_OK_MASK)!=SG_INFO_OK) {return 2;} /* inquiry command failed */

for (i=0;i<96;i++) {
output[i]=reply_buffer[i];
}
return 1; /*succes*/
}

int main () {
/* initialize various vars.*/
FILE *driveptr;

int i;

char OSpointer[9];

unsigned char output1[96],
output2[96],
serialinq[6]={SERIALINQUIRY}, /* var to store SCSI inquiry for serial number */
modelinq[6]={MODELINQUIRY}; /* var to store SCSI inquiry for model string */

for (i=0;i<DRIVEAMOUNT;i++) {
strcpy(OSpointer,"/dev/sdX");
OSpointer[7]='a'+i;

driveptr=fopen(OSpointer,"r");
if (driveptr==NULL) {
continue;
}

if (SCSI_sendcmd(fileno(driveptr),modelinq,output1)==1) {printf("model:|%s|\n",output1);}
if (SCSI_sendcmd(fileno(driveptr),serialinq,output2)==1) {printf("serial:|%s|\n",output2);}
printf("\n");

fclose(driveptr);
}
}

Answer

early parts of the string have terminating('\0') characters, %s only prints out until such a character is reached! either removing them or printing out each char in a loop!

Comments