Команды запроса scsi для получения информации о серийном номере и модели

У меня проблемы с получением информации о серийном номере и модели с дисков SCSI через запрос. Мой запрос всегда возвращает пустые строки.

Вот быстрый и грязный код запроса, который должен, по крайней мере, вывести весь ответ запроса. Вывод не отформатирован для получения конкретной информации, но он все равно должен работать. Но это не так.

#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);
    } 
}

person John Smith    schedule 11.02.2014    source источник


Ответы (3)


ранние части строки имеют завершающие ('\0') символы, %s распечатывается только до тех пор, пока такой символ не будет достигнут! либо удаляя их, либо распечатывая каждый символ в цикле!

person John Smith    schedule 11.02.2014
comment
Это не дает ответа на вопрос. Чтобы подвергнуть критике или запросить разъяснения у автора, оставьте комментарий под его сообщением — вы всегда можете прокомментировать свои собственные сообщения, и как только у вас будет достаточно репутация, вы сможете комментировать любой пост. - person Corley Brigman; 11.02.2014

for (i=0;i<96;i++) {
       output[i]=reply_buffer[i];
}

должно начинаться с reply_buffer[4]

person user3381635    schedule 05.03.2014

Использование отладчика для SCSI_sendcmd() для проверки содержимого replay_buffer или output показало бы, как выглядит результат. Пример (гдб):

(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>
person U. Windl    schedule 25.10.2016