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!
scsi inquiry commands to get serial and model information
-
09-10-2022 - |
Question
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);
}
}
Solution
OTHER TIPS
for (i=0;i<96;i++) {
output[i]=reply_buffer[i];
}
should start at reply_buffer[4]
Using a debugger for SCSI_sendcmd()
to inspect the contents of replay_buffer
or output
would have shown how the result looks like.
Example (gdb):
(gdb) n
34 output[i]=reply_buffer[i];
(gdb) p reply_buffer
$2 = "\000\000\005\002[\000\000\000ATA WDC WD7500AVDS-60A01", '\000' <repeats 23 times>, "`\003 \002`", '\000' <repeats 31 times>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow