Home / Alt manpages / sg_read_buffer(8)

  • sg_read_buffer(8)
  • Admin command
  • linux

Read SCSI Buffer Data Safely with sg_read_buffer

You will finish with a repeatable way to query a SCSI device's READ BUFFER response, inspect it as decoded text or hexadecimal, and decode a saved response without touching hardware. Allow about fifteen minutes. You need the sg3-utils package and either a SCSI generic device such as /dev/sg3, or a response fixture to decode.

The examples below use the installed sg_read_buffer from Ubuntu package sg3-utils 1.46-3ubuntu4. Its own version output is 1.30 20191220, so record both values when comparing behaviour between machines. The installed help also exposes READ BUFFER(16); the local May 2019 manpage documents the original command form and its modes.

1. Confirm the installed command

Start with read-only checks. They need no elevated privileges:

$ command -v sg_read_buffer
/usr/bin/sg_read_buffer
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_read_buffer --version
version: 1.30 20191220

Read the local option list before copying an example from another host:

$ sg_read_buffer --help
Usage: sg_read_buffer [--16] [--help] [--hex] [--id=ID] [--inhex=FN]
                      [--length=LEN] [--long] [--mode=MO] [--offset=OFF]
                      [--raw] [--readonly] [--specific=MS] [--verbose]
                      [--version] DEVICE

Checkpoint

The executable is from the expected package, and you know which options this installed build accepts. The package version and the utility's printed version do not match exactly here. That is a packaging detail, not a reason to infer undocumented defaults.

2. Choose a device and a harmless first query

Find the device name from your storage documentation or an inventory command. Do not guess a disk from its position in /dev. A SCSI generic node is usually the least surprising target for sg3_utils:

$ ls -l /dev/sg*
$ ls -l /dev/disk/by-id/

Querying a real device sends a SCSI command. It is not a write operation, but a device can reject an unsupported mode or allocation length, and some hardware has fragile firmware. Start with the descriptor mode and the documented four-byte default:

$ DEVICE=/dev/sg3
$ sg_read_buffer --readonly --mode=desc --length=4 "$DEVICE"
OFFSET BOUNDARY: 0, Buffer offset alignment: 1-byte
BUFFER CAPACITY: 4 (0x4)

The exact values are device-specific. A successful exit status is zero. Output like "Invalid field in CDB" means the device rejected this command combination; it does not prove that the device path is wrong.

Safety boundary

--readonly opens the device read-only, while the command itself is a READ BUFFER command. Keep it in diagnostic examples. The default open mode is read-write, so do not omit it casually on a shared or sensitive host. Elevated privileges are only needed if the device node permissions require them:

$ sudo sg_read_buffer --readonly --mode=desc --length=4 "$DEVICE"

3. Understand the mode and allocation length

--mode controls the MODE field in the SCSI command. The local manpage accepts decimal, hexadecimal, or an acronym. Use the installed program to list its available names:

$ sg_read_buffer --mode=xxx 2>&1
The modes parameter argument can be numeric (hex or decimal)
or symbolic:
  0 (0x00)  hd
  1 (0x01)  vendor
  2 (0x02)  data
  3 (0x03)  desc
 10 (0x0a)  echo
 11 (0x0b)  echo_desc
 15 (0x0f)  rd_microc_st
 26 (0x1a)  en_ex
 28 (0x1c)  err_hist

The descriptor mode returns four bytes describing offset alignment and buffer capacity. The data and echo modes can return actual buffer content, while vendor and error-history modes depend on the device. Do not switch to a data-bearing mode simply because it sounds more useful.

--length places an allocation length in the command. Its default is 4 bytes, and the device may return fewer bytes. Increase it only when the response format requires more data, for example:

$ sg_read_buffer --readonly --mode=echo --length=64 "$DEVICE"

--id selects the buffer identifier, defaulting to 0. --offset is a byte offset and defaults to 0. --specific is a three-bit mode-specific value from 0 to 7. These fields are part of the device and SCSI specification, not local file offsets. Keep their defaults until the target documentation gives you a reason to change them.

4. Inspect a response without hardware

--inhex makes the device optional. It reads ASCII hexadecimal or binary response data from a file, then decodes it as though it came from READ BUFFER. This is the safest way to test parsing and share a fixture:

$ cat > /tmp/read-buffer-descriptor.hex <<'EOF'
00 00 00 04
EOF
$ sg_read_buffer --inhex=/tmp/read-buffer-descriptor.hex --mode=desc
OFFSET BOUNDARY: 0, Buffer offset alignment: 1-byte
BUFFER CAPACITY: 4 (0x4)

Whitespace and commas separate byte values, and text after a hash mark is ignored. Add --mode and --specific when decoding because those command fields are not included in the response:

$ sg_read_buffer --inhex=/tmp/read-buffer-descriptor.hex \
    --mode=desc --specific=0

Remove the temporary fixture when it is no longer useful:

$ rm -- /tmp/read-buffer-descriptor.hex

That removal is the only state change in this fixture workflow. If the file is evidence, preserve it under your normal evidence-retention policy instead of deleting it.

5. Choose text, hexadecimal, or binary output

Descriptor responses are decoded by default. Use --hex to see bytes, which is usually the right choice when the response is undocumented:

$ sg_read_buffer --readonly --mode=desc --hex "$DEVICE"
00 00 00 04

Give --hex twice for hexadecimal with an ASCII representation alongside it. Use --raw only when another program needs binary on standard output. Never send raw output directly to your terminal or a text log:

$ sg_read_buffer --readonly --mode=echo --length=64 --raw "$DEVICE" \
    > /tmp/read-buffer-response.bin
$ file /tmp/read-buffer-response.bin
$ od -Ax -tx1 -c /tmp/read-buffer-response.bin | sed -n '1,12p'

Binary output may contain control characters or sensitive device data. Protect the file according to the device's data classification and remove it with your normal retention procedure when finished. Do not use --raw together with a terminal-facing diagnostic command.

6. Use READ BUFFER(16) only when required

The installed help provides --16 for READ BUFFER(16), while the older local manpage does not list it. Prefer the default command on a target that documents the ten-byte command. Use the extended form only when the device or protocol requires it, and check the installed help on that host:

$ sg_read_buffer --readonly --16 --mode=desc --length=4 "$DEVICE"

Do not assume that a device supporting SCSI also supports every READ BUFFER mode or command length. If this returns a sense error, capture the error text, retry the documented command form, and check the device vendor's SCSI support matrix. More verbosity can help an investigation:

$ sg_read_buffer --readonly --verbose --mode=desc --length=4 "$DEVICE"
$ printf 'exit status: %s\n' "$?"

Done means

  • You confirmed the installed sg3-utils package and sg_read_buffer version.
  • You selected a documented SCSI device path and retained --readonly.
  • You used descriptor mode first, with the four-byte default understood.
  • You can distinguish decoded, hexadecimal, and binary output.
  • You can decode a saved response with --inhex and the missing mode context supplied explicitly.
  • You treat READ BUFFER(16), raw files, vendor modes, and device-specific errors as deliberate choices.