Provided by: ddpt_0.97-1_amd64 bug

NAME

       ddpt_sgl - helper for ddpt utility's scatter gather lists

SYNOPSIS

       ddpt_sgl  [--action=ACT] [--a-sgl=SGL] [--b-sgl=SGL] [--chs=CHS] [--degen=DV] [--document]
       [--elem=SE[,LE]] [--extension=FNE] [--flexible] [--help] [--hex] [--iaf=IAF]  [--index=IA]
       [--interleave=IL]  [--non-overlap]  [--out=O_SGL]  [--quiet]  [--round=RB] [--sort-cmp=SC]
       [--stats] [--verbose] [--version]

DESCRIPTION

       This utility is a scatter gather list helper  for  the  ddpt  utility  which  copies  data
       between  or  within  SCSI  devices  (logical  units).  While ddpt's command line syntax is
       modelled on that of the POSIX dd command, this utility has a more  standard  Unix  command
       line syntax with both short and long variants of each option.

       Scatter  gather lists (sgl_s) are made up of scatter gather elements. Each element is made
       up a starting logical block address (LBA) and a number of blocks (NUM) from and  including
       that LBA.

       The scatter gather lists can also be viewed as arrays in which elements can be accessed by
       an index. Multiple sgl elements can be accessed with an  array  of  indexes,  hence  index
       arrays.  Indexes  in  this  utility start at 0 and run to (n - 1) where n is the number of
       elements in the sgl. Also negative indexes are permitted where -1 is the index of the last
       sgl element, -2 is the index of the second last sgl element, etc.

       For  "twin"  actions  there is an assumed relationship between a-sgl and b-sgl as there is
       between two sgl_s used as the gather list (e.g. skip=) and the scatter list  (e.g.  seek=)
       in  the ddpt utility. Breaking it down to individual logical blocks: LBAr0 is read and its
       data  is  written  to  LBAw0,  LBAr1-->LBAw1,  LBAr2-->LBAw2,  etc;  or   more   generally
       LBAr_n-->LNAw_n.  Many actions will change the order in which those "read-write" items are
       performed, the twin portion  of  the  action  attempts  to  maintain  the  LBAr_n-->LNAw_n
       mapping.  Generally  speaking,  copies are the same no matter what order the LBAs are read
       and written. One exception is an overlapping scatter list (i.e.  on  the  write  side)  in
       which  case the order of writes onto the same LBA does matter, hence there is an option to
       check sgl_s are well-formed in that respect: --non-overlap.

       For background on scatter gather lists see the section of that name in the ddpt(8) manpage
       found in this package. There is a web page at https://sg.danny.cz/sg/ddpt.html .

OPTIONS

       Arguments to long options are mandatory for short options as well.

       -a, --action=ACT
              ACT  is  some  action  to perform on the given scatter gather list(s).  To list the
              available actions set ACT to 'xxx' (or 'enum'). The available actions are listed in
              the ACTIONS section below.

       -A, --a-sgl=SGL
              SGL  is  a scatter gather list, a sequence of comma separated unsigned integers (up
              to   64   bits   each).   SGL    has    several    forms,    the    simplest    is:
              LBA0,NUM0,LBA1,NUM1,LBA2,NUM2...  and there should be an even number of values with
              the exception of LBA0 appearing by itself. In this case NUM0 is assumed  to  be  0.
              Other  SGL  forms  are  '@<filename>'  and 'H@<filename>' where the contents of the
              <filename> is parsed as a scatter gather list.  Since there  are  two  options  for
              inputting SGLs, this one is termed as the 'a-sgl'.
              See  the  section  on FILE FORMATS below and the section on SCATTER GATHER LISTS in
              the ddpt(8) manpage for more information on sgl_s and their associated terminology.

       -B, --b-sgl=SGL
              SGL is a scatter gather list, a second list termed as the 'b-sgl' to  differentiate
              it from the other sgl (a-sgl).

       -C, --chs=CHS
              CHS  is  a  3 element tuple, separated by commas. Currently 16 bit values from 1 to
              0xffff are accepted (the cylinder can be one more: 0x10000 (or 65536)).  The  first
              value  is the number of cylinders, the second value is the number of heads (limited
              to 16), and the final value is the number of sectors per track  (limited  to  255).
              Sectors  are  counted  origin 1 according to CHS conventions (cf. normal LBAs which
              nearly always count from 0).

       -D, --degen=DV
              DV of 0 (the default) means that all degenerate elements (apart from the last)  are
              ignored (and dropped from the internal representation which may later be written to
              an output file). If DV is odd then a degenerate element's LBA is taken into account
              when  calculating  the  highest  and lowest LBA in a sgl (and may be included in an
              output file). If DV is even (apart from a DV of 0) then a degenerate element's  LBA
              it taken into account when determining if a sgl is monotonic increasing, decreasing
              or neither (and may be included in an output file).

       -d, --document
              this option causes information about the a sgl or index  array  to  be  written  as
              comments  (i.e. lines starting with '#') to the beginning of output file(s) created
              by this utility.
              If this option is given twice then the command line that caused the output is added
              to the file as a comment (before any numbers are output).

       -E, --elem=SE[,LE]
              this  option  allows a single sgl element (at position SE (starting element index))
              to be output to O_SGL or O_SGL.FNE (or IAF). SE is origin 0. If  LE  (last  element
              index)  is  given  then  a range of sgl elements are output starting at index SE to
              index LE inclusive. If a "twin" operation is being performed then this option  only
              applies  to the "a" side output, not the "twin" side. This option is ignored by the
              output of the split_n and tsplit_n actions.

              Negative values for either SE or  LE  count  from  the  end  of  sgl.  For  example
              --elem=0,-1 refers to the whole of the list.
              If LE is less than SE (after any negative indexes are converted to their equivalent
              positive index) then that range is output in reverse.

       -e, --extension=FNE
              FNE is the filename  extension  used  when  output  filenames  are  generated.  For
              non-split  actions  the  generated  filenames  are of the form: O_SGL.FNE . For the
              split_n action the generated filenames are of the form: O_SGL[1..n].FNE .  For  the
              tsplit_n action the a-sg is named as per the previous sentence, while for the b-sgl
              the generated filenames are of the form: O_SGL[1..n]_t.FNE .
              If O_SGL is '-' (by itself) then all output is sent to stdout and  this  option  is
              ignored.

       -f, --flexible
              this  option  effects  the  parsing (reading) of sgl_s and index arrays that are in
              files which are in hexadecimal. Such files should have a leading line (i.e.  before
              any  numbers)  with  'HEX' on it. Without this option any such file must be invoked
              with 'H@' before the filename; in other words the 'H' in the  invocation  needs  to
              match the 'HEX' in the file. With this option a file can be invoked with '@' and if
              a line with 'HEX' is parsed before any numbers  then  it  switches  to  hexadecimal
              mode; so that all the parsed numbers are assumed to be in hexadecimal.

       -h, --help
              outputs the usage message summarizing command line options then exits.

       -H, --hex
              used to define the numeric format of sgl and index array elements written to output
              (often a file named O_SGL or stdout). If not given then  only  decimal  values  are
              written  to  output. If this option is given once then hexadecimal values, prefixed
              with '0x', are written. If this option is given twice then a line with  the  string
              'HEX'  is  written  to  output,  before any values, and those values are implicitly
              hexadecimal (i.e. no leading '0x' nor 'h' suffix).

       -I, --iaf=IAF
              where IAF is a filename (or '-' for stdout) to write an index array  to.  The  only
              action  that  generates an index array currently is --action=sort (and tsort). This
              option can be together used with, or in place of, the --out=O_SGL option.
              The --document, --elem=SE[,LE] and --hex options effect what is  written.  See  the
              section on FILE FORMATS below.

       -x, --index=IA
              where  IA is one or more indexes, comma separated or, if prefixed by "@" or "H@", a
              filename  containing  a  list  of  indexes.  These  indexes   are   used   by   the
              --action=select  and --action=tselect to select elements from the 'a-sgl'. Positive
              and negative indexes that are too large (in absolute terms) are ignored and  create
              noise if the --verbose option is given. See the section on FILE FORMATS below.

       -i, --interleave=IL
              IL  is  an  integer,  starting  from  0.  When  IL  is  0 (the default) there is no
              interleave. The interleave only effects the split_n and tsplit_n actions  and  when
              greater  than  zero is the maximum number of logical blocks written in each segment
              in the output file, prior to moving to the next output file.
              For the case where IL is 1 and --action=split_1 is given then the output file  will
              have  every  LBA (given by the a-sgl) as a separate sgl element (and thus each will
              have a NUM of 1).
              For the tsplit_n action the interleave is only applied to the  a-sgl  but  it  does
              effect the twin sgl files.

       -N, --non-overlap
              Checks  any  given sgl and any resulting sgl (from an action) to see if any portion
              of the sgl overlaps. This is done by first sorting each sgl by the LBA field,  then
              checking  every  element against the previous one to determine if there is overlap.
              SCSI commands that accept sgl_s process degenerate elements without  error  but  if
              two  elements  in  a  WRITE  command overlap then it is the storage device's choice
              which one to WRITE first. The last one to be  written  will  be  the  one  read  in
              subsequent read operations.
              If  no errors are detected then if (all) are non-overlapping then 0 is returned. If
              no errors are detected then if (any) are overlapping then 36 is returned.

       -o, --out=O_SGL
              O_SGL is the name of a file to write a resultant scatter gather list to.  If  O_SGL
              is  '-'  then  the output is directed to stdout.  If O_SGL starts with '+' then the
              output is appended to the file whose name follows the '+'.
              For the split and tsplit actions, the leading '+' is interpreted as appended to all
              files  that  meet  the template and exist, otherwise the file is created. If '-' is
              given then all output is directed to stdout (and  the  --extension=FNE  option,  if
              given, is ignored).

       -q, --quiet
              suppresses  warning  and  messages  announcing  an  action has succeeded. When this
              option is given, actions that have a logical (boolean) result don't output messages
              but still yield an indicative exit status. The exit status will typically be either
              0 for true or 36 for false.  are typically sent to stderr.

       -r, --round=RB
              RB is the number of round blocks. Without the option the split_n action will divide
              the  number of blocks to be split by '<n>' (or use IL) to get a nominal value. This
              value is the number of blocks taken from the a-sgl before moving to the next output
              file.  The  RB  value (default 0) is the maximum number of blocks the nominal value
              may be changed by to align with an existing element boundary in the a-sgl.
              If the number of blocks in 'a-sgl is less than 10 or RB is greater than  one  third
              of the nominal value, then RB is ignored (with a notification written to stderr).
              For the tsplit_n action this option only applies to the a-sgl.

       -S, --sort-cmp=SC
              where  SC  is a value indicating what the sort action's comparison will be. When SC
              is 0 (the default) the sort is ascending based on the LBA; when it is 1 the sort is
              descending  based  on LBA. When SC is 2 the sort is ascending based on NUM; when it
              is 3 the sort is descending based on NUM. Any other value is mapped to 0. All sorts
              are stable which means that sgl elements with the same LBA (in the case of SC being
              0 or 1) keep their same relative position. A  side  effect  of  this  is  that  the
              ascending and descending sorts are not always reversals of one another.

       -s, --stats
              print out sgl statistics on any given sgl and any resultant sgl.

       -v, --verbose
              increase the level of verbosity, (i.e. debug output).

       -V, --version
              print the version string and then exit.

ACTIONS

       Actions  are  given on the command line as part of the --action=ACT option. Currently only
       one action is allowed per invocation. If more are allowed in  the  future,  they  will  be
       comma separated and performed in the order in which they appear (i.e. left to right).

       If  no  action  is  given and the --a-sgl=SGL and --out=O_SGL options (with no --b-sgl=SGL
       option) are given then the a-sgl is copied to O_SGL (or O_SGL.FNE if  the  --extension=FNE
       option is given).

       The actions are listed below in alphabetical order.

       append-b2a
              appends  the  b-sgl  to  the  end  of the a-sgl and outputs the result to O_SGL (or
              O_SGL.FNE if the  --extension=FNE  option  is  given).  Requires  the  --a-sgl=SGL,
              --b-sgl=SGL and --out=O_SGL options.

       divisible<n>[,L|N] or divisible_<n>[,L|N]
              where  <n>  is  an  integer, 1 or higher. This action checks if each LBA and NUM in
              a-sgl is divisible by <n> (where 'is divisible' is equivalent to having a remainder
              of  zero).  If  all  are  divisible then true is returned (i.e. the exit status 0);
              otherwise false is returned (i.e.  exit status 36).
              If the optional ",L" suffix (or ",LBA") is given then  only  each  LBA  element  in
              a-sgl  is  checked  for  divisibility. If the optional ",N" suffix (or ",NUM") then
              only each NUM element in a-sgl is checked for divisibility.
              The output of the string to stderr announcing divisibility, or lack of it,  can  be
              suppressed by the --quiet option.

       enum   prints  out  the  list of supported actions then exits. Giving the action 'xxx' has
              the same effect.

       equal  this action compares the sgl_s given to --a-sgl=SGL and --b-sgl=SGL.  If  the  same
              LBAs  are  in  the  same  order  with  the  same  overall number of blocks (but not
              necessarily the same number of elements) then  true  is  returned  (i.e.  the  exit
              status  0); otherwise false is returned (i.e.  exit status 36). For example the two
              element sgl "0x10,0x5, 0x15,0x2" is 'equal' to the one element sgl "0x10, 0x7".
              The output of the string to stderr announcing equality,  or  lack  of  it,  can  be
              suppressed by the --quiet option.

       none   this  action  does  nothing.  This  is  the  default  action.  If  --a-sgl=SGL  and
              --out=O_SGL options are given and no other action, then a-sgl is copied to O_SGL.
               It is a placeholder.

       part-equal
              this action is similar to the equal action but  relaxes  the  condition  that  both
              lists  must have the same overall number of blocks. For example the two element sgl
              "0x10,0x5, 0x15,0x2" is 'part-equal' to the one element sgl "0x10, 0x12".

       part-same
              this action is similar to the same action but relaxes the condition that both lists
              must  have  the  same  overall  number  of  blocks. For example the two element sgl
              "0x15,0x2,0x10,0x5" is 'part-same' as the one element sgl "0x10, 0x12".

       same   this action is similar to the equal action but  relaxes  the  condition  that  both
              lists  must  be in the same order. The implementation sorts both given lists before
              comparing them.  For example the two element sgl "0x15,0x2, 0x10,0x5" is the 'same'
              as the one element sgl "0x10, 0x7".

       scale<n> or scale_<n>
              where  <n>  is  an integer, positive or negative but not zero. When <n> is positive
              then the starting LBA and the NUM in each a-sgl element is multiplied by <n> .  The
              new (scaled) sgl is written to O_SGL (or O_SGL.FNE if the --extension=FNE option is
              given).
              When <n> is negative then the absolute value of <n> is used as a divisor  for  each
              starting LBA and NUM in each a-sgl element.
              As  an example: converting a 512 byte logical block (LB) size sgl to a 4096 byte LB
              size and vice versa is relatively common. To convert from 4096 --> 512 byte LB size
              then  --action=scale_8  is  appropriate.  To convert from 512 --> 4096 byte LB size
              then --action=scale_-8 is appropriate.
              Note: because an integer division is used (that rounds 'towards zero') when <n>  is
              negative  then  LBs  or  NUMs may be "lost" in this conversion. This can be checked
              beforehand with the --action=divisible<n>[,L|N] option. For example:  for  512  -->
              4096 conversions: --action=divisible_8 will report if any starting LBAs or NUMs are
              not divisible be 8 and hence are not able to be precisely represented as 4096  byte
              LB addresses or number of 4096 byte blocks.

       select this  action  can  be  used  to  select  a subset (or superset) of the a-sgl in the
              specified order. Alternatively it can be seen as re-ordering the elements in  a-sgl
              such  as is done toward the end of a sort operation. Assuming all the indexes in IA
              are valid, then the O_SGL file will have the same number of elements as  there  are
              indexes in IA.
              This  option  requires  non-empty  --a-sgl=SGL  and  --index=IA  options,  plus the
              --out=O_SGL option.

       sort   this action will sort the sgl given by --a-sgl=SGL in ascending order by  LBA.  The
              resulting  sgl  is  output  to O_SGL (or O_SGL.FNE if the --extension=FNE option is
              given).
              The sort is "stable", so if two elements have the same starting LBA then they  will
              appear in the same relative order in the output.

       split<n> or split_<n>
              where  <n>  is  an  integer,  1 or higher. This action divides --a-sgl=SGL into <n>
              roughly equal length (i.e. number of blocks) output sgl_s.  The  output  files  are
              named  "O_SGL<1..n>"  or "O_SGL<1..n>.FNE". Both the --interleave=IL and --round=RB
              options are taken into account during the split process.

       to-chs this action takes the 'flat' LBA SGL given to --a-sgl=SGL and converts it into  CHS
              (cylinder/head/sector)  based  SGL which is written out as directed to --out=O_SGL.
              This  action  requires  the  --chs=CHS  option  as  well  as  the  --a-sgl=SGL  and
              --out=O_SGL options.

       tselect
              this is a "twin select" action that selects from --a-sgl=SGL (a-sgl) then re-orders
              --b-sgl=SGL (b-sgl) in unison. The select from a-sgl is the same as described under
              the  select  action above. Additionally b-sgl is is broken up so it has "breaks" at
              the same positions (i.e. number of blocks from the start of the sgl) as a-sgl does;
              plus  the  "breaks"  b-sgl  has  already got. So the "broken up" b-sgl will have at
              least as many elements as a-sgl. The output of the re-ordered b-sgl is then written
              to O_SGL_t or O_SGL_t.FNE if the --extension=FNE option is given.

       tsort  this  is  a  "twin  sort"  action  that  sorts  --a-sgl=SGL  (a-sgl)  and re-orders
              --b-sgl=SGL (b-sgl) in unison. The sort of a-sgl is the same as described under the
              sort  action  above.  Additionally  b-sgl is is broken up so it has "breaks" at the
              same positions (i.e. number of blocks from the start of the  sgl)  as  a-sgl  does;
              plus  the  "breaks"  b-sgl  has  already got. So the "broken up" b-sgl will have at
              least as many elements as a-sgl. The re-ordering vector  generated  by  the  stable
              sort  of a-sgl is then applied to the broken up b-sgl. The output of the re-ordered
              b-sgl is then written to O_SGL_t or O_SGL_t.FNE if the  --extension=FNE  option  is
              given.

       tsplit<n> or tsplit_<n>
              this  is  a  "twin  split"  action that splits the --a-sgl=SGL and --b-sgl=SGL into
              separate series of output files. These separate series  maintain  the  LBA  to  LBA
              correspondence  of  the  original  a_sgl  and  b_sgl lists. <n> is an integer, 1 or
              higher. This action divides --a-sgl=SGL into <n> roughly equal length (i.e.  number
              of  blocks)  output  sgl_s.  The  "roughly  equal  length"  is  influenced  by  the
              --interleave=IL and --round=RB options. The output filenames are generated the same
              way as described for the split action. The sgl from --a-sgl=SGL is expected to be a
              "hard" sgl which means its last element should not be degenerate (i.e. have  a  NUM
              of 0).
              The  second  half  of  the  "twin  split" is to split the --b-sgl=SGL sgl. The same
              number of output files are used as for the  'A'  side  but  the  filenames  have  a
              slightly   different   form:   "O_SGL<1..n>_t"   or   "O_SGL<1..n>_t.FNE"  (if  the
              --extension=FNE option is given). The critical point of this split is that it moves
              in  lockstep  with the 'A' side split in the sense that whatever block count an 'A'
              side segment uses, the following 'B' side segment split uses the same block  count.
              The  sgl  from  --b-sgl=SGL may be a "hard" or "soft" sgl. In the simplest case the
              'B' side sgl can be just '0' which gets expanded to  '0,0'  (i.e.  degenerate  list
              starting at LBA 0); this will use the overall block count from the 'A' side.

FILE FORMATS

       Both  sgl_s  and  index  arrays  can be read from, or written to, files.  The options that
       supply sgl_s or index arrays to be read (e.g.  --a-sgl=SGL, --b-sgl=SGL and --index=IA) by
       default allow them to be given directly on the command line. These will typically be comma
       separated lists (although space  and  tab  could  be  used  as  separators  if  they  were
       appropriately  escaped).  So  with  these  options  when reading sgl_s and index arrays, a
       leading "@" or "H@" is needed to indicate that a file name follows.

       By default, numbers given in this utility and other utilities in this package are  assumed
       to  be  in  decimal.  Hexadecimal (hex) numbers can be given with either a leading "0x" or
       trailing "h". A whole file can be flagged as containing hex numbers (and thus not  needing
       a  leading  "0x" nor trailing "h" on each number) by using "H@" on the command line before
       the filename. The file itself may contain a line with 'HEX' in it, prior  to  any  numbers
       that  are  to be parsed. If the --flexible option is given then "@" can be used before the
       filename and when 'HEX' is detected in the file (before any numbers) the code switches  to
       hex  mode.  Without  the  --flexible  option  "H@"  must  be use before the filename. As a
       convenience the 'HEX' string may appear after hex numbers have been decoded and it will be
       ignored.  This is to allow hex sgl_s files to be concatenated together and still be parsed
       without error.

       A file being parsed may contain comments following a "#"  symbols.   Everything  from  and
       include  the  hash  mark  to  the  end  of a line is ignored. Blank lines and "whitespace"
       (spaces, tabs, CRs and LFs) are also ignored.

       If large sgl_s or index arrays are being used it is better to have one element per line in
       the  file  to  be  read. This is because a line is not expected to be over 1024 bytes long
       with more than 254 parsable items on it.  This utility imposes no limit on the  number  of
       lines a file to be parsed may have.

       Files  to  be  written  out  by this utility have their names specified by the --out=O_SGL
       (optionally together with --extension=FNE) and the  --iaf=IAF  options.  Unlike  the  file
       reading options, no "@" character should be placed in front of the filename on the command
       line. If a filename of "-" is given then output is written to stdout instead  of  a  file.
       stdout  is  normally  the  console. If the filename starts with "+" then that character is
       skipped the output will be appended to that file, if it exists.  If  the  filename  starts
       with  "+" and the file does not exist then it is created. If "+" is not given and the file
       already exists then it is truncated (to 0) then overwritten. Some output file  names  have
       numbers  (e.g.  as a result of the --action=spilt_<n> option) or "_t" (e.g. as a result of
       "twin" actions) appended to them (before the extension, if any). Sgl elements  are  output
       one  per  line,  with  a comma separating the LBA and the NUM. Index arrays are output one
       element (an index) per line. The --hex option controls the form of those  numbers  output.
       If --hex is not given, the numbers are output in decimal. If the --hex option is given one
       the number are output in hex with a "0x" prefix. If the --hex option is given  twice  then
       the  line  'HEX'  is  written  to the file before any numbers and those numbers are in hex
       without any adornment (i.e. with no leading "0x").

       If the --document option is given then some information  including  a  date  timestamp  of
       generation  is  placed  as comments at the beginning of files that are written out by this
       utility. If the --document option is given twice then the invocation line of this  utility
       that caused the output is placed in the written file as an additional comment.

       The  written  file  format is compatible with the read file format. So, for example, a sgl
       generated by a invocation of this utility can later be used  as  a  file  to  be  read  by
       another invocation of this utility.

EXIT STATUS

       The exit status of ddpt_sgl is 0 when it is successful. Note that some options and actions
       that return a boolean value return 0 for true and 36 for false. Otherwise the exit  status
       for this utility is the same as that for ddpt. See the EXIT STATUS section in the ddpt man
       page.

EXAMPLES

       Examples are needed. See testing/test_sgl.sh script in this package. That  script  can  be
       run without root permissions and places its work file (sgl_s) in the /tmp directory.

AUTHORS

       Written by Douglas Gilbert.

REPORTING BUGS

       Report bugs to <dgilbert at interlog dot com>.

COPYRIGHT

       Copyright © 2020-2021 Douglas Gilbert
       This  software  is distributed under a FreeBSD license. There is NO warranty; not even for
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

SEE ALSO

       ddpt(8), ddptctl(8)