Sending scsi command to drive

I’ve just started programming with Go and I have a few questions. I have gone thru many forums regarding SCSI commands, but the requirement is different.

  1. Sending SCSI cmd to a drive
    a) The available sg3_utils cannot be used due to proprietary SCSI command.

    b) I was able to formulate the 16 byte CDB but don’t know how to send the CDB to /dev/

    c) if exec.command has to be used , the first arg has to be exe , so unfortunately cannot use this command.

How do I send CDB to the device and get the return status ?

Thank you


If you want to run a program, then use exec.Cmd, if though you want to write to a device file in /dev, you have to open it for writing using file and io related packages in go.

Thank you Norbert,

I had a look at the cmd structure and have a clarification

type Cmd struct {
// Path is the path of the command to run.
// This is the only field that must be set to a non-zero // value.

Path string

  1. Does “Path” represents the one byte operation code (opcode) ?

  2. Currently I have hardcoded the CDB[16]
    cdb[0] = op_code
    cdb[1] = wrprotect and so on…

    ret = exec.Command(…) // not sure how to pass the cdb as the first parameter in the command followed by input file and the dev/

Path is the path to the executable/command you want to run. Basically what you would write in your terminal, with the exception, that no PATH lookup will happen.

There is a helper function available which will create a Cmd struct with prefilled Path and Args: exec.Command()

You can see an example usage of it in my playground with ls.

Currently writing the program in Ubuntu environment.

I used one of the sg3_utils (sg_compare_write)

cmd := exec.Command(“sg_compare_write”, …) and was successfully able to execute the cmd

But due to few changes in the requirements, can no longer use this command .

So either I write my own exe or find a way to send the CDB to the device.

This might sound very naive but I tried to pass the CDB as first parameter in the exe.Command and got the foll.message

this exec: “cdb”: executable file not found in $PATH

So to use exec.Command(), the first parameter has to be formulated.

Without using exec.Command() , any other way to send the cdb to the drive like using (ioctl ?)

Thank you @NobbZ for the reply. Hope I can fix this at the earliest.

You can use whatever you use on your terminal using exec.Cmd/exec.Command().

cdb is not a byte… Therefore not sure what you are saying. Perhaps show real code?

Anyway, if you can not use executables that are already available on your system, you have to mimic what they do.

They might call into the kernel directly, they might for themself just shell into another tool, they might write to /dev/… directly, I do not know the tool(s) you are talking about…

New to programming world and here is the source code
Currently I have hard-coded the sw_cdb for testing purpose.

func scsi_cmd(){

var sw_cdb[16] int64

sw_cdb[0]	= opcode //proprietary code
sw_cdb[1] 	= 10
sw_cdb[2]	= 01
sw_cdb[3] 	= FF 
sw_cdb[4]	= FF
sw_cdb[5] 	= FF
sw_cdb[6]	= FF
sw_cdb[7] 	= FF
sw_cdb[8]	= FF
sw_cdb[9] 	= FF
sw_cdb[10]	= 00
sw_cdb[11] 	= 00
sw_cdb[12]	= 00
sw_cdb[13] 	= 03	//NBLK
sw_cdb[14]	= 02
sw_cdb[15] 	= 00

if (NLBK > 0) {

	var out bytes.Buffer
	var stderr bytes.Buffer

	s_ret := exec.Command(??,"-i","inputF1.bin","--v","-l","400","/dev/sg2","-g","1","-x","512")
            // Q1. How to send sw_cdb command to the drive. There is no equivalent exe to fill '??'
            // Q2. Either I mimic the sg_compare_write exe and I have no idea how to create an exe 
            // Q3. What other possible way to send this sw_cdb to the drive ? 

        	s_ret.Stdout = &out
	s_ret.Stderr = &stderr
	c_error := s_ret.Run()


Thank you.


What would you write on a terminal?


Sorry, i didn’t understand your question
Are you talking about commands?

Yes. exec.Command and exec.Cmd are about starting programs, to emulate what you would usually do on a terminal.


Sorry for delay reply.
I was able to send the commands to the drive using ioctl. Since we are framing own commands to be sent to the drive, cannot use available utilities like sg3_utils in the exec.Command(). So changed the code to open the device and send the command via ioctl. Tested using sg_inq.

I will post my code soon, if able to read the data from the drive. Thank you so much @NobbZ.
I will update you soon


This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.