Imported Upstream version 2.5.2 upstream upstream/2.5.2
authorBdale Garbee <bdale@gag.com>
Tue, 20 May 2008 05:00:10 +0000 (23:00 -0600)
committerBdale Garbee <bdale@gag.com>
Tue, 20 May 2008 05:00:10 +0000 (23:00 -0600)
37 files changed:
.indent.pro [new file with mode: 0644]
COPYING [new file with mode: 0644]
Changes [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
dds-dd.man [new file with mode: 0644]
dds-dd.ps [new file with mode: 0644]
dds2index.man [new file with mode: 0644]
dds2index.ps [new file with mode: 0644]
dds2tar-test.sh [new file with mode: 0755]
dds2tar.c [new file with mode: 0644]
dds2tar.h [new file with mode: 0644]
dds2tar.lsm [new file with mode: 0644]
dds2tar.man [new file with mode: 0644]
dds2tar.ps [new file with mode: 0644]
dds_chkhdr.c [new file with mode: 0644]
dds_extract.c [new file with mode: 0644]
dds_index.c [new file with mode: 0644]
dds_quote.c [new file with mode: 0644]
dds_tape.c [new file with mode: 0644]
dds_tape.h [new file with mode: 0644]
ddstool [new file with mode: 0755]
index-of-dds2index [new file with mode: 0644]
index-of-tar [new file with mode: 0644]
index-of-tar-t [new file with mode: 0644]
index-of-tar-v [new file with mode: 0644]
mt-dds.man [new file with mode: 0644]
mt-dds.ps [new file with mode: 0644]
scsi_vendor [new file with mode: 0755]
tar-1.11.2-sparse-files.README [new file with mode: 0644]
tar-1.11.2-sparse-files.patch [new file with mode: 0644]
tar-1.11.2.patch [new file with mode: 0644]
tar-1.11.8.patch [new file with mode: 0644]
tar-1.12.patch [new file with mode: 0644]
tar-1.13.patch [new file with mode: 0644]
zf-cre-open.c [new file with mode: 0644]
zf-cre-open.h [new file with mode: 0644]

diff --git a/.indent.pro b/.indent.pro
new file mode 100644 (file)
index 0000000..f22fd9a
--- /dev/null
@@ -0,0 +1,3 @@
+-bad  -bap -bbb -nsob -cdb -sc -br -cli0 -ss -npcs -cs -bs -di8 -i8 -lp
+-ts8 -ce -l78 -Ttar_record
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..572fd8d
--- /dev/null
+++ b/Changes
@@ -0,0 +1,243 @@
+Version 2.5.1  changed J"org Weule (weule@7b5.de) at 13-AUG-2000
+              - Thorsten Kranzkowski <dl8bcu@gmx.net> has send me a patch
+                with a bug fix. Now the listing created by
+                'mt-dds tell;tar -Rt' created by an unpatched tar can be used.
+Version 2.5.0  changed J"org Weule (weule@7b5.de) at 6-AUG-2000
+              - Roland Wundrig has send me a patch to eliminate quoted
+                substrings from the index file. In order to alow the user
+                to use a quoted or unquoted form on the command line,
+                I coded this feature in a different way.
+Version 2.4.21 chanded by J"org Weule (weule@acm.org) at 1998 Aug 5.
+              - Added Exabyte as a tape vendor.
+Version 2.4.20 chanded by J"org Weule (weule@acm.org) at 1998 Jul 28.
+              - Andrew Ukrainec (ukrainec@infoukes.com) pointed out,
+                that there is a mistake in the patch of tar inside the
+                online documentation of the new option. I fixed that.
+Version 2.4.19 chanded by Erkki Myllynen (erkki@sweden.hp.com)
+              - A bug was found inside the tar patch, the calculation
+                of the thoughtput is fixed now.
+Version 2.4.18 chanded by Chris Hanson (cph@martigny.ai.mit.edu)
+              - Bug fix for dds_index.c to handle LF_LONGNAME records at
+                the end of tape blocks correctly.
+Version 2.4.17 chanded by J"org Weule at 1998 May 25.
+              - I've deleted the set_density, because HP drives
+                are operating with variable block sizes well and
+                othter drives don't support changing the density.
+              - The blocksize is now the buffer size of the program.
+                read_ahead is only possible for root and deleted in this
+                version.
+              - The calculation of the block numer is changed
+Version 2.4.16 chanded by J"org Weule
+              - scsi_vendor: Added a script to examine the drive vendor.
+              - on non archive tapes, the blocksize is set to one.
+                These drives can not handle other block sizes.
+                Read-ahead is enabled to enhence performance.
+              - dds_extract.c: Added #define _GNBU_SOURCE for compilation
+                on new systems like RedHat5.0.
+Version 2.4.15 changed by J"org Weule at 1997 Dec 9.
+              - dds_extract.c: bug-fix, short index lines
+              - dds_extract.c: support for tar-1.12 verbose listing
+
+Version 2.4.14 changed by J"org Weule at 1997 Nov 30.
+              - dds_extract.c: bug-fix
+              - dds_tape.c: to make the program working under HP-UX 
+                thanks to Les.Grant@mitsuibabcock.co.uk
+                for his patch, sended to me at 1997 Nov 28:
+Version 2.4.13 changed by J"org Weule at 1996 Dez 1. :
+              - Added support for long filenames. Long filenames
+                are handled with "tar cv ..." and dds2index to create
+                the index table. "tar xv ..." is not writing an index
+                dds2tar can handle correct with long file names.
+                A filename is called long, if it has more than 99 characters.
+              - Fixed problems matching the index with the header records
+                of the tape. I made the check more robust.
+Version 2.4.12 changed by J"org Weule at 1996 Mar 29. :
+              - fixed the strncmp calls inside dds2tar.c - thanks to
+                Goncal Badenes <badenes@imec.be> for the bug fix.
+              - fixed dds_extract.c --
+                tar cfv and tar vft are reporting soft _and_ hard links
+                in a different style. Hard links may not confuse the
+                header test in dds_extract.
+                Goncal Badenes <badenes@imec.be> for the bug fix.
+              - Added a test with an unpatched tar into dds2tar-test.sh.
+
+Version 2.4.11 changed by J"org Weule at 1996 Mar 10. :
+              - Added a warning: You have to be root to change compression.
+              - Added dds-dd, a tool to read a tape with unknown block size.
+
+Version 2.4.10 changed by J"org Weule at 1996 Feb 5. :
+              - Fixed my tar-patch. Sorry for the mistake.
+
+Version 2.4.10 changed by J"org Weule at 1996 Jan 4. :
+              - Changed the counter --totals with tar-1.11.8-patch to
+                'long long int' to use very large archives.
+                Added the calculation of the throuput on --totals.
+              - Fixed the dds2tar-test.sh script.
+              - Test for elf compatibility.
+
+Version 2.4.9 changed by J"org Weule at 1995 Feb 4. :
+              - Added the action filename to mt-dds.
+
+Version 2.4.8 changed by J"org Weule at 1995 Feb 4. :
+              - Added option 'date <timestammp>' to mt-dds.
+              - Fixed the code for 'mt-dds ts'
+              - tar-1.11.2.patch:
+                Added %T to expand the record-filename with the timestamp.
+
+Version 2.4.7 changed by J"org Weule at 1995 Feb 2. :
+              - Added a patch to tar (support for sparse file on Linux boxes).
+              - dds_bsr() inserted to dds_tape.c and used by mt-dds (label).
+                A small change of ddstool was necessary
+
+Version 2.4.6 changed by J"org Weule at 1995 Jan 29. :
+              - added the option ts to mt-dds.
+              - added the option date to mt-dds.
+              - added teh script 'ddstool' to make some things easier.
+              - fixed the handling of softlinks in conjunction with
+                tar index file -- dds2tar ended with FATAL error in
+                this case.
+              - added a tool tar2tar.
+
+Version 2.4.5 changed by J"org Weule at 1994 Dez 22. :
+              - On non HP-DDS devices, teh record number is read from
+                the device before any block is read.
+              - Added the option --quick to skip reading of parent directories.
+
+Version 2.4.4 changed by J"org Weule at 1994 Dez 3. :
+
+Version 2.4.3 changed by J"org Weule at 1994 Nov 21. :
+              - Added a test script with index files to the package.
+              - Added --body to dds2tar.
+              - Added label to mt-dds.
+
+Version 2.4.2 changed by J"org Weule at 1994 Nov 21. :
+              - Fixed some bugs of dds_extract.c.
+
+Version 2.4.1 changed by J"org Weule at 1994 Nov 7. :
+              - Andreas Bagge was kind enought to report a bug:
+                Long files (>1MB) are shifting the name field in the tar
+                listing to the right. dds_extract.c is now able to detect
+                this.
+              - I moved the check about the line '-end- ...' to the begining
+                of the loop inside dds_extract.c.
+              - Fixed a bug of mt-dds. tell was not working at all.
+              - Tried to include code to set the right buffer size
+                in order to allow the change of the buffer of the kernel.
+                The size of the internal buffer can be set by the -b option
+                (command line or environment) or is extracted from the
+                tar record file if possible. The internal buffer should be
+                large enought to hold one tape block.
+              - As Andreas Bagge pointed out, a parameter to fnmatch()
+                serves for matching filenames by giving the directory
+                entry. The matching is now done similar to tar.
+              - A workaround lets you create an index of tapes created
+                with 'tar -b 256 ...' on SunOS. You may have to increase
+                the default buffer size (ST_BUFFER_BLOCKS) inside the
+                Makefile to 64 or bigger and the kernel
+                (/usr/src/linux/drivers/scsi/st.c) in that case. On SunOS I
+                recommend a block size smaller or equal than 64 (-b option of
+                tar = 32Kb). You have also to increase the buffer size
+                of your kernel (/usr/src/linux/drivers/scsi/st.c).
+                The default buffer size of the kernel is the maximal block
+                size of tape block which can be read is 32kB.
+              - The option --body is included.
+
+Version 2.4.0 changed by J"org Weule at 1994 Oct 28. :
+              - Fnmatch() was found inside clib (gclib). Code deleted.
+
+Version 2.3.9 changed by J"org Weule at 1994 Oct 16. :
+              - Reading some options from the environment, e.g. -z, -s, -b.
+
+Version 2.3.8 changed by J"org Weule at 1994 Oct 15. :
+              - Added a check for the header at dds2index.
+                If it's not a tar header, a skip is performed.
+
+Version 2.3.7 changed by J"org Weule at 1994 Oct 13. :
+              - change the tar-1.11.2 patch to get the date of archiving
+                in the listing (bug fix). The date of the label record is
+                printed correct now while creating the archive.
+              - New options --z and --no-compress are included.
+              - The environment variable DDS2TAR should contain the string
+                --compress to set this option to default.
+              - The default DEVICE is now /dev/rmt0 like tar.
+
+Version 2.3.6 changed by J"org Weule at 1994 Oct 11. :
+              - A lot of header files are created. Some source files
+                are divided into two.
+              - As Andreas Bagge pointed out, main(argc,argv,envp) is not
+                ANSI-C code. I deleted envp for that reason, but this still
+                works.
+              - I changed the interface to open child processes. Now you
+                find a nice interface at "zf-cre-open.c". You may open
+                a pipe to the child process for reading or writing on a
+                file number of your choice, e.g. 0 or 1 ('creopen()').
+                (Writing stderr to a child process is not supported.)
+                The function 'zfopen()' opens a file for reading or writing
+                with transparent (de)compression. This may also be of interest
+                for other programs.
+
+Version 2.3.5 changed by J"org Weule at 1994 Oct 11. :
+              - Added -fwritable-strings to the compiler options
+                Constant strings are declared const by hand.
+
+Version 2.3.4 changed by J"org Weule at 1994 Oct 10. :
+              - Inserted a lot of const declarations and fixed a bug
+                inside an experimental function.
+              - Added the postscript versions of the manual pages to the
+                distribution.
+
+Version 2.3.3 changed by J"org Weule at 1994 Oct 10. :
+              - No access to tape with -l.
+              - Inserted some lines for security.
+                If the name of the program is mt-dds, nothing is
+                written on the disk by the program.
+
+Version 2.3.2 changed by J"org Weule at 1994 Oct 10. :
+              - bug fix inside dds_extract.c.
+
+Version 2.3.1 changed by J"org Weule at 1994 Oct 9. :
+              - All header record are checked for the filename.
+              - New option -l is included to check the index file for the
+                selected matches. The strings are written to stdout and no
+                pipeing to tar should be done.
+              - option --extract included.
+
+Version 2.3.0 changed by J"org Weule at 1994 Oct 9. :
+              - Added a check inside dds2tar. Now some header records of the
+                tar files to extract are checked for the expected file name.
+                dds2tar should stop if you have inserted the wrong tape.
+              - I inserted a routine to open stdout for a child process or
+                a file. Andreas Bagge gave me some source to create the
+                included functions.
+              - A funktion tar-dds is added to write a tool like tar.
+                The tool is not ready yet.
+              - Added background information to the man page of dds2tar.
+                The lines are based on a text from Andreas Bagge.
+
+Version 2.2.0 changed by J"org Weule:
+              I have deleted a lot of options to make the software easier to use.
+              The scan of the index file is very robust.
+
+              Hope you agree that dds2tar should be a small tool, simple to
+              use and with as less parameters as possible. That's why I have
+              deleted old and obsolete parameters for the costs that you may
+              have to change some scripts.
+
+Version 2.1.2 Index lines strings with '#' are ignored.
+              mt-dds can be used to set the tape position of the tape
+                for the next run of dds2tar. This may be convenient for
+                shell scripts.
+
+Version 2.1.1 The recfile (-R) can also be an index-file created by dds2index.
+              The option -t of dds2tar is obsolete.
+              Help is written to stdout.
+
+Version 2.1.0 made some options obsolete.
+
+Version 2.0.1 is a package with a patch to tar-1.11.2.
+
+Version 2.0.0 is a package of three programs, to make it easier to use.
+              A lot of options of dds2tar-1.1.3 are included.
+              So it is easy to switch to this new version.
+
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6b75897
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,231 @@
+# Makefile for dds2tar
+#
+#--------------------------------------------------------
+# To compile everything:                     make
+# To install the executables and man pages:  make install
+#--------------------------------------------------------
+
+V=2.5.2
+
+# Here are some configurable options:
+################################################################
+
+# To enable the use of the log pages of an HPDAT,
+# uncomment the following line :
+HPDAT=-DHPDAT
+
+# Default tape device is: /dev/nst0
+# edit or uncomment the following line to change the default device
+DEVICE=/dev/rmt0
+
+# Enable trace mode -- for debugging only
+# TRACE=-DDDS_TRACE=1
+
+# The tape blocks are read into a buffer, so the buffer of dds2tar
+# should be in the same size as the one in /usr/src/linux/driver/scsi/st.c
+# of the kernel code. Set ST_BUFFER_BLOCKS to zero, in order to take the
+# size from the kernel source directly.
+#
+# The number is halved, if EOVERFLOW is detected.
+# The value of the kernel is normally ST_BUFFER_BLOCKS=32.
+#
+# To configure the buffer size of dds2tar
+# change or uncomment the following line :
+# BUFFER=-DST_BUFFER_BLOCKS=32
+BUFFER=-DST_BUFFER_BLOCKS=0
+
+# To include some experimental stuff
+# uncomment the following line :
+# EXP_STUFF=-DEXP_STUFF
+
+# change this to where you want to install:
+BINDIR=/usr/bin
+MANDIR=/usr/man
+MANEXT=1
+
+# place here your favorite C compiler and options
+CC=cc -g
+CCOPT=$(HPDAT) $(HPDAT4) $(EXP_STUFF) $(MATCH) $(BUFFER) \
+      -DDEVICE=\"$(DEVICE)\" -O4 -Wall $(TRACE)
+
+#        -Wall \
+#        -Wstrict-prototypes \
+#        -Wshadow \
+#        -Wwrite-strings \
+#        -Wpointer-arith \
+#        -Wcast-qual \
+#        -Wenum-clash \
+#        -Wcast-align \
+#        -Wtraditional \
+#        -Wmissing-prototypes \
+#        -Wnested-externs \
+#        -Winline \
+#        -pedantic \
+
+# nothing configurable below this line
+################################################################
+
+.SUFFIXES: .c .o .man .$(MANEXT) .ps .s
+
+D=dds2tar-${V}
+
+CCFLAGS=-DVERSION=\"$V\"
+
+TAR=tar
+ARCHIVE=\
+$(D)/Makefile \
+$(D)/Changes \
+$(D)/README \
+$(D)/dds2tar.man \
+$(D)/dds2index.man \
+$(D)/mt-dds.man \
+$(D)/dds-dd.man \
+$(D)/dds2tar.ps \
+$(D)/dds2index.ps \
+$(D)/mt-dds.ps \
+$(D)/dds-dd.ps \
+$(D)/dds2tar.h \
+$(D)/dds2tar.c \
+$(D)/dds_extract.c \
+$(D)/zf-cre-open.h \
+$(D)/zf-cre-open.c \
+$(D)/dds_index.c \
+$(D)/dds_tape.h \
+$(D)/dds_tape.c \
+$(D)/dds_chkhdr.c \
+$(D)/dds_quote.c \
+$(D)/scsi_vendor \
+$(D)/tar-1.11.2.patch \
+$(D)/tar-1.11.8.patch \
+$(D)/tar-1.12.patch \
+$(D)/tar-1.13.patch \
+$(D)/tar-1.11.2-sparse-files.patch \
+$(D)/tar-1.11.2-sparse-files.README \
+$(D)/dds2tar-test.sh \
+$(D)/index-of-tar \
+$(D)/index-of-tar-v \
+$(D)/index-of-tar-t \
+$(D)/index-of-dds2index \
+$(D)/.indent.pro \
+$(D)/dds2tar.lsm \
+$(D)/COPYING \
+$(D)/ddstool \
+
+
+OBJ= dds_index.o dds_extract.o dds_tape.o dds_quote.o \
+     zf-cre-open.o dds_chkhdr.o
+
+
+all: dds2tar dds2tar.1 dds2index.1 mt-dds.1 dds-dd.1
+
+dds2tar: dds2tar.o $(OBJ)
+       $(CC) dds2tar.o $(OBJ)  -o dds2tar
+       ln -f dds2tar dds2index
+       ln -f dds2tar mt-dds
+       ln -f dds2tar dds-dd
+
+tar2tar: tar2tar.c
+       $(CC) tar2tar.c -o tar2tar
+
+dds2index: dds2index.o $(OBJ)
+       $(CC) dds2index.o $(OBJ)  -o dds2index
+
+mt-dds: mt-dds.o $(OBJ)
+       $(CC) mt-dds.o $(OBJ)  -o mt-dds
+
+dds-dd: dds-dd.o $(OBJ)
+       $(CC) dds-dd.o $(OBJ)  -o dds-dd
+
+install: dds2tar ddstool \
+       dds2tar.$(MANEXT) mt-dds.$(MANEXT) dds2index.$(MANEXT) dds-dd.$(MANEXT)
+       install -c -s dds2tar $(BINDIR)
+       install scsi_vendor $(BINDIR)
+       install -c ddstool $(BINDIR)
+       ls -l $(BINDIR)/dds2tar $(BINDIR)/ddstool
+       install -c dds2tar.$(MANEXT)   $(MANDIR)/man$(MANEXT)
+       install -c dds2index.$(MANEXT) $(MANDIR)/man$(MANEXT)
+       install -c mt-dds.$(MANEXT)    $(MANDIR)/man$(MANEXT)
+       install -c dds-dd.$(MANEXT)    $(MANDIR)/man$(MANEXT)
+       ln -f $(BINDIR)/dds2tar  $(BINDIR)/dds2index
+       ln -f $(BINDIR)/dds2tar  $(BINDIR)/mt-dds
+       ln -f $(BINDIR)/dds2tar  $(BINDIR)/dds-dd
+
+T=tar-1.13
+tar: dds2tar.ps dds2index.ps mt-dds.ps dds-dd.ps ${T}.patch
+       -cd .. ; echo ' ' ; \
+               $(TAR) -R -c -f $(D).tar -v $(ARCHIVE) ;
+               echo ' '
+       ls -l ../$(D).tar
+       gzip -9 -f ../$(D).tar
+       ls -l ../$(D).tar.gz | awk '{print $$5}' > archive_length
+       sed s/LENGTH/`cat archive_length`/ <dds2tar.lsm |\
+           sed s/VERSION/$(V)/ > ../$(D).lsm
+       ls -l ../dds2tar*z ../dds2tar*.lsm
+       -rm -f ../dds2tar archive_length
+       cd .. ; ln -s $(D) dds2tar
+       echo ' '
+       cd .. ; tar zfc ${T}.1.tar.gz --totals ${T}.1
+       cd .. ; tar cf archive.tar ${D}.lsm ${D}.tar.gz ${T}.1.tar.gz
+
+tar-patch tar-1.13.patch: 
+       ls -l tar-*patch
+       cd ..; diff -ru ${T} ${T}.1 |grep -v 'Only in '> $(D)/${T}.patch ;true
+       ls -l tar-*patch
+
+.c.o:
+       $(CC) -c $< $(CCOPT) $(CCFLAGS)
+
+.c.s:
+       $(CC) -S -c $< $(CCOPT) $(CCFLAGS)
+
+.man.1:
+       umask 022 ; sed -e 's?/dev/tape?$(DEVICE)?' $< >$@
+
+.man.ps:
+       umask 022 ; sed -e 's?/dev/tape?$(DEVICE)?' $< >$*.1
+       umask 022 ; groff -man $*.$(MANEXT)   > $*.ps
+
+clean:
+       -rm -f $(OBJ) dds2tar.o dds2index.o mt-dds.o dds-dd.o *.BAK *.s
+       -rm -f dds2tar dds2index mt-dds dds-dd fio_test 
+       -rm -f *~ *.$(MANEXT) *.ps
+       -rm -f tags *.bak
+       chmod 644 *
+
+doc:
+                       a2ps -p -nP    [A-Z]* *.h *.c *.lsm > a.ps
+       man dds2tar   | a2ps -p -nP -m -Hdds2tar            > b.ps
+       man dds2index | a2ps -p -nP -m -Hdds2index          > c.ps
+       man mt-dds    | a2ps -p -nP -m -Hmt-dds.man.ps      > d.ps
+       man dds-dd    | a2ps -p -nP -m -Hdds-dd.man.ps      > d.ps
+
+psman: dds2tar.$(MANEXT) mt-dds.$(MANEXT) dds2index.$(MANEXT) dds-dd.$(MANEXT)
+       groff -man dds2tar.$(MANEXT)   > dds2tar.ps
+       groff -man dds2index.$(MANEXT) > dds2index.ps
+       groff -man mt-dds.$(MANEXT)    > mt-dds.ps
+       groff -man dds-dd.$(MANEXT)    > dds-dd.ps
+
+dds_quote.o:dds_quote.c dds2tar.h
+dds_extract.o:dds_extract.c dds2tar.h dds_tape.h
+dds_index.o:dds_index.c dds2tar.h dds_tape.h
+dds_quote.o:dds_quote.c dds2tar.h
+dds_tape.o:dds_tape.c dds2tar.h dds_tape.h
+zf-cre-open.o:zf-cre-open.c zf-cre-open.h
+
+INC=dds2tar.h dds_tape.h zf-cre-open.h
+dds2tar.o:dds2tar.c $(INC)
+       $(CC) -c dds2tar.c $(CCOPT) $(CCFLAGS) -DPROGRAM=DDS2TAR -o dds2tar.o
+dds2index.o:dds2tar.c $(INC)
+       $(CC) -c dds2tar.c $(CCOPT) $(CCFLAGS) -DPROGRAM=DDS2INDEX -o dds2index.o
+mt-dds.o:dds2tar.c $(INC)
+       $(CC) -c dds2tar.c $(CCOPT) $(CCFLAGS) -DPROGRAM=MTDDS -o mt-dds.o
+dds-dd.o:dds2tar.c $(INC)
+       $(CC) -c dds2tar.c $(CCOPT) $(CCFLAGS) -DPROGRAM=MTDDS -o dds-dd.o
+
+fio_test:zf-cre-open.c zf-cre-open.h
+       cc zf-cre-open.c -DTEST -o fio_test
+
+tags:
+       ctags -stv *.c
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..47aaf18
--- /dev/null
+++ b/README
@@ -0,0 +1,179 @@
+
+    dds2tar  Digital-Data-Storage Extract Tool for LINUX and HP-UX
+
+             This tool makes use of the fast seek command of DAT devices.
+             Files from a selected file archive can be extracted within
+             one minute.
+
+             This tool was originally written for Linux SCSI tape archives.
+             All device dependent code is separated.
+             It should be easy, to change this for your machine type.
+             The only problem should be the ioctls for
+                MTIOCTOP,(MTSEEK,arg) and MTIOCPOS.
+
+             Les.Grant@mitsuibabcock.co.uk send me a patch to make it
+             working under HP-UX, thanks.
+
+             Other patches epsecially for Solaris are welcome.
+
+             J"org Weule                     weule@cs.uni-duesseldorf.de
+                                             Fon: +49 211 751409
+
+             This software is available at
+
+                         ftp.uni-duesseldorf.de:/pub/unix/apollo
+
+             ( This is my personal directory, I started writing PD-software
+               on Apollo-Computers, but they are dying now :-( . Now you
+               will find some other stuff there.)
+
+----------------------------------------------------------------------------
+
+                              LICENSE
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published
+    by the Free Software Foundation; either version 1, or (at your option) 
+    any        later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+----------------------------------------------------------------------------
+
+                              DESCRIPTION
+
+To extract a file from a tape, you have to know the location of the file.
+A tar archive is a sequence of tar records, 512 byte each. The blocksize
+(tar -b #) selects the number of tar records inside each block of the tape.
+(HP is calling the blocks of the tape records also.)
+
+The location of a file is a tuple of the block number and the number of the
+record where the header of the file can be found inside the block.
+
+The first step will be to extract a table with block and record information
+of all files in one archive. If the archive is the 10'th file of the tape,
+you will get the table by:
+
+             mt asf 10
+             dds2index -t my-archive-table -f /dev/nst0
+
+Tar is writing some record information to stdout, when you select the options
+-R and -v. To use this information as a location table, you have to know the
+block number of the first block and the blocksize of the archive. If it's the
+first archive of the tape and the blocksize is the default of 20, you can
+use the verbose lines of tar as a location table. (Additional lines with
+warnings can be included). Otherwise you have to patch tar to retrieve the
+location information. If you don't want to patch tar, feel free to insert
+the output of 'mt-dds tell' at the top of the verbose output of tar.
+
+If you have applied the patch file 'tar-1.12.patch' to GNU tar, you can use 
+the verbose output of the tar command (tar -c -v --record-file F) instead of the
+index file generated with the dds2index command above.
+
+(If you patch tar-1.12, you are able to write the record-information
+ to a file while getting the errors on screen. The patch 'tar-1.12.patch'
+ adds the option '--record-file F'. Additionally a small bug in the source file
+ 'create.c' of tar is fixed. I have moved one line to correct the verbose output
+ of the record numbers. While creating the archive, you can store the current
+ time at the label record. A bug fix to write this date to the verbose output
+ is also done in the source file 'list.c'.)
+
+ !  The patch tar-1.12.patch moves one line inside the source file 'create.c'
+ !  and adds some lines for the ability to direct the verbose output to a file.
+ !  Two extra lines are printed to the terminal in some cases to get to current
+ !  tape position at the start and the blocksize.
+ !  Nothing else is done. There should be no extra risk for your data.
+ !  The tar will stay fully compatible to the original version.
+ !  The patch is also convenient for other operating systems.
+
+Lines of the index file stating with '#' are ignored. So you can insert
+some comments. This distribution includes some examples of index files.
+Look for files 'index-of-*'
+
+Once you have the table, you can get the files very quickly. Lets suppose,
+you want to extract everything of the glibc, you have to invoke
+the following command:
+
+             dds2tar -t my-archive-table 'glibc*' | tar -f - -xvv
+
+dds2tar will search in the archive table for the blocks to read, and 
+extracts the records with the selected files. These records together
+are giving a valid tar archive, to use tar for restoring to your disk.
+This will also work, if the files are not a continuous area of the tape.
+dds2tar is skipping over the gaps very quickly with a seek command.
+If you want to extract exactly one file, use -x instead of -p.
+If you want to extract all files, witch named include a pattern,
+use -g instead of -p or -x.
+A list of files is valid to search for. 
+
+With the option -z, you can force the index file to be in compressed mode.
+Compressed archive files are not supported.
+If you  don't use the option -t, stdin or stdout are used in this case.
+The default device is /dev/nst0, witch can be overwritten by the TAPE variable
+and the option -f.
+
+If you want to get familiar with the command, use 
+
+             # skipping to some file
+             mt rewind
+             mt fsf 20
+
+             # creating the table of the archive
+             dds2index -t my-archive-table 
+
+             # The following line is an alternative way to create the index.
+             # You have to patch tar to make the option --record-file
+             # available.
+             # tar -t --record-file my-archive-table
+
+             # extract all files with the substring glibc in there names
+             # and use tar to check the output of dds2tar.
+             dds2tar -t my-archive-table 'glibc*' | tar -f - -tvv
+             # See what's going on ...                  ^^^^ ^^
+
+to see what's going on. In any case, dds2tar is reading your tape,
+so don't worry. Only the file specified by -t is written by this example.
+
+NOTE:
+To make extraction easier, dds2tar will also extract the directories
+for the selected files. So you will also get the full directory hierarchy.
+
+The owners of HP-DAT devices will find the actions comp-on, comp-off and
+comp-query (dds-compression-mode) of mt-dds convenient to change the compression
+mode of the device. Turning off the compression will speed up storing
+'gzip'ed files.
+
+WARNING:
+If we seek to the first block of a file, it can happen, that we are
+going to the position before the filemark. The program is closing and opening
+the file in that case to step over the filemark. Don't use /dev/st0 in that
+case, use /dev/nst0.
+
+THANKS:
+Thanks to Andreas (Andreas_Bagge@h2.maus.de), who has send me a new manual
+page, witch gave me the ideas how to split dds2tar-1.1.3 into peaces.
+His page was also the starting point for the approved man-page added to this
+version.
+
+Thanks also to Chris Hanson (cph@martigny.ai.mit.edu) for his bug bix.
+
+Last change 2.2.95 by J"org Weule
+
+----------------------------------------------------------------------------
+
+                              INSTALLATION
+
+1. Change the "Makefile" to reflect the buffersize of the kernel.
+   Otherwise uncomment the definition of BUFFER.
+
+2. type "make install".
+
+3. patch tar-1.12 if you like.
+
diff --git a/dds-dd.man b/dds-dd.man
new file mode 100644 (file)
index 0000000..d8ad7d5
--- /dev/null
@@ -0,0 +1,82 @@
+.TH dds-dd 1L 2.4 \" -*- nroff -*-
+.\"----------
+.SH NAME
+.\"----------
+dds-dd \- tool to read a dds device.
+.\"----------
+.SH SYNOPSIS
+.\"----------
+.B dds-dd
+[
+.B -f device
+]
+.PD 1
+.\"----------
+.SH DESCRIPTION
+.\"----------
+.B dds-dd
+reads a dds tape devices (DAT). Every block is read and written to
+stdout. A tape with unknown block size or blocks of different size
+can be read.
+.PP
+The default device is
+.IR /dev/rmt0 ,
+which may be overridden with the environment variable
+.BR TAPE ,
+which in turn may be overridden with the
+.BI -f \ device
+option. The device must be a character special file.
+.\"----------
+.SH OPTIONS
+.\"----------
+.TP
+.BI -f\  device
+Device of the tape archive (default is /dev/rmt0).
+Must be a character special file connected to a dds tape device.
+.TP
+.BR -V , --version
+Print the version number of
+.B mt-dds
+to stderr and exit immediately.
+.TP
+.B --help
+print some screens of online help with examples through a pager
+and exit immediately.
+.\"----------
+.SH EXAMPLES
+.\"----------
+.B Example: 
+Read the tape and make a listing:
+.RS 10
+dds-dd | tar ft -
+.RE
+.PP
+.B Example: 
+Read the tape and make a listing:
+.RS 10
+dds-dd | cpio -it 
+.RE
+.PP
+.PD 1
+.\"----------
+.SH ENVIRONMENT
+.\"----------
+The environment variable
+.B TAPE
+overrides the default tape device /dev/rmt0.
+.TP
+.\"----------
+.SH "SEE ALSO"
+.\"----------
+dds2tar(1), dds2index(1), mt(1), tar(1)
+.\"----------
+.SH HISTORY
+.\"----------
+This program was created to use it in conjunction with dds2tar.
+.\"----------
+.SH AUTHOR
+.\"----------
+J"org Weule (weule@cs.uni-duesseldorf.de), Phone +49 211 751409.
+This software is available at
+ftp.uni-duesseldorf.de:/pub/unix/apollo
+
diff --git a/dds-dd.ps b/dds-dd.ps
new file mode 100644 (file)
index 0000000..a27075a
--- /dev/null
+++ b/dds-dd.ps
@@ -0,0 +1,246 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.09
+%%CreationDate: Sun Mar 10 17:12:19 1996
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.09 0
+%%Pages: 1
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.09 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 375.52(dds-dd\(1L\) dds-dd\(1L\))72 48 R/F1 9
+/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0
+(dds-dd \255 tool to read a dds de)108 96 Q(vice.)-.25 E F1(SYNOPSIS)72
+112.8 Q/F2 10/Times-Bold@0 SF(dds-dd)108 124.8 Q F0([)2.5 E F2(-f de)2.5
+E(vice)-.15 E F0(])2.5 E F1(DESCRIPTION)72 148.8 Q F2(dds-dd)108 160.8 Q
+F0 .975(reads a dds tape de)3.475 F .975(vices \(D)-.25 F -1.11(AT)-.4 G
+.975(\). Ev)1.11 F .975
+(ery block is read and written to stdout. A tape with unkno)-.15 F(wn)
+-.25 E(block size or blocks of dif)108 172.8 Q(ferent size can be read.)
+-.25 E .726(The def)108 196.8 R .726(ault de)-.1 F .726(vice is)-.25 F
+/F3 10/Times-Italic@0 SF(/de)3.226 E(v/rmt0)-.15 E F0 3.226(,w).47 G
+.726(hich may be o)-3.226 F -.15(ve)-.15 G .726(rridden with the en).15
+F .726(vironment v)-.4 F(ariable)-.25 E F2 -.9(TA)3.226 G(PE).9 E F0
+3.226(,w)C .726(hich in)-3.226 F(turn may be o)108 208.8 Q -.15(ve)-.15
+G(rridden with the).15 E F2(-f)2.5 E F3(de)2.5 E(vice)-.15 E F0
+(option. The de)2.5 E(vice must be a character special \214le.)-.25 E F1
+(OPTIONS)72 232.8 Q F2(-f)108 244.8 Q F3(de)2.85 E(vice)-.15 E F0(De)144
+256.8 Q .792(vice of the tape archi)-.25 F 1.091 -.15(ve \()-.25 H(def)
+.15 E .791(ault is /de)-.1 F 3.291(v/rmt0\). Must)-.25 F .791
+(be a character special \214le connected to a)3.291 F(dds tape de)144
+268.8 Q(vice.)-.25 E F2(-V)108 292.8 Q F0(,)A F2(--v)A(ersion)-.1 E F0
+(Print the v)144 304.8 Q(ersion number of)-.15 E F2(mt-dds)2.5 E F0
+(to stderr and e)2.5 E(xit immediately)-.15 E(.)-.65 E F2(--help)108
+328.8 Q F0(print some screens of online help with e)11 E
+(xamples through a pager and e)-.15 E(xit immediately)-.15 E(.)-.65 E F1
+(EXAMPLES)72 352.8 Q F2(Example:)108 364.8 Q F0(Read the tape and mak)
+2.5 E 2.5(eal)-.1 G(isting:)-2.5 E(dds-dd | tar ft -)158 376.8 Q F2
+(Example:)108 400.8 Q F0(Read the tape and mak)2.5 E 2.5(eal)-.1 G
+(isting:)-2.5 E(dds-dd | cpio -it)158 412.8 Q F1(ENVIR)72 448.8 Q
+(ONMENT)-.27 E F0(The en)108 460.8 Q(vironment v)-.4 E(ariable)-.25 E F2
+-.9(TA)2.5 G(PE).9 E F0 -.15(ove)2.5 G(rrides the def).15 E
+(ault tape de)-.1 E(vice /de)-.25 E(v/rmt0.)-.25 E F1(SEE ALSO)108 496.8
+Q F0(dds2tar\(1\), dds2inde)144 508.8 Q(x\(1\), mt\(1\), tar\(1\))-.15 E
+F1(HIST)72 532.8 Q(OR)-.162 E(Y)-.315 E F0(This program w)108 544.8 Q
+(as created to use it in conjunction with dds2tar)-.1 E(.)-.55 E F1 -.45
+(AU)72 568.8 S(THOR).45 E F0(J"or)108 580.8 Q 3.028(gW)-.18 G .528
+(eule \(weule@cs.uni-duesseldorf.de\), Phone +49 211 751409.)-3.828 F
+.528(This softw)5.528 F .529(are is a)-.1 F -.25(va)-.2 G .529
+(ilable at ftp.uni-).25 F(duesseldorf.de:/pub/unix/apollo)108 592.8 Q
+220.25(2.4 1)299.75 768 R EP
+%%Trailer
+end
+%%EOF
diff --git a/dds2index.man b/dds2index.man
new file mode 100644 (file)
index 0000000..e836388
--- /dev/null
@@ -0,0 +1,132 @@
+.TH dds2index 1L 2.4 \" -*- nroff -*-
+.\"----------
+.SH NAME
+.\"----------
+dds2index \- tool to create an indexfile for the use of
+.\"----------
+.SH SYNOPSIS
+.\"----------
+.B dds2index
+[options]
+.\"----------
+.SH DESCRIPTION
+.\"----------
+.B dds2index
+creates an index file that is required by the file extraction utility
+.BR dds2tar(1) .
+It works on 
+.B tar 
+archives stored on dds tape devices (DAT).
+Since the file structure of the tape archives is
+used to extract the files, the archive must be an 
+.B uncompressed tar 
+archive. But compression by the transparent
+signal processor of the tape device is allowed.
+.PP
+The index created by
+.BR dds2index
+is written to 
+.I stdout 
+by default and should normally be stored on hard disk as 
+.I indexfile 
+for later use by 
+.BR dds2tar(1) .
+.PP
+The default tape device to read from is
+.IR /dev/tape ,
+which may be overridden with the environment variable
+.BR TAPE ,
+which in turn may be overridden with the
+.BI -f\  device
+option. The device must be a SCSI tape device.
+.PP
+.\"----------
+.SH OPTIONS
+.\"----------
+.TP
+.BI -f\  devicefile
+device of the tape archive. Must be a character special file.
+.TP
+.BI -t\  indexfile
+write the index to 
+.IR indexfile ,
+not to
+.IR stdout.
+.TP
+.BR -z , --compress
+write the index in (gzip) compressed mode.
+.TP
+.B --help
+print some screens of online help with examples through a pager
+and exit immediatley.
+.\"----------
+.SH OPTIONS you didn't really need
+.\"----------
+.TP
+.B -b, --block-size
+Set the maximal blocksize, dds2index can handle.
+.TP
+.TP
+.B --z, --no-compress
+Don't filter the archive file through gzip.
+.TP
+.BR -v , --verbose
+verbose mode. Print to 
+.IR stderr 
+what is going on. 
+.TP
+.BR -h , --hash-mode
+Print a hash sign '#' to 
+.I stderr 
+for each MB read from tape.
+.TP
+.BR -V , --version
+Print the version number of
+.B dds2index
+to 
+.I stderr 
+and exit immediately.
+.\"----------
+.SH EXAMPLES
+.\"----------
+.RP
+Example of getting the index from the default tape /dev/tape
+and storing it in file archive.idx:
+.IP
+dds2index -v -t archive.idx
+.\"----------
+.SH WARNING
+.\"----------
+This program can only read records (tar is calling them tape blocks)
+up to 32 kbytes. A bigger buffer will cause problems with the Linux
+device driver.
+.\"----------
+.SH ENVIRONMENT
+.\"----------
+The environment variable
+.B TAPE
+overrides the default tape device /dev/tape.
+.\"----------
+.SH FILES
+.\"----------
+.TP 14
+/dev/tape
+default tape device file. Must be a character special file.
+.\"----------
+.SH "SEE ALSO"
+.\"----------
+dds2tar(1), mt(1), mt-dds(1), tar(1), gzip(1)
+
+.\"----------
+.SH HISTORY
+.\"----------
+This program was created as a tool for 
+.BR dds2tar(1) .
+
+.\"----------
+.SH AUTHOR
+.\"----------
+J"org Weule (weule@cs.uni-duesseldorf.de), Phone +49 211 751409.
+This software is available at
+ftp.uni-duesseldorf.de:/pub/unix/apollo
+
diff --git a/dds2index.ps b/dds2index.ps
new file mode 100644 (file)
index 0000000..6258d59
--- /dev/null
@@ -0,0 +1,286 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.09
+%%CreationDate: Sun Mar 10 17:12:15 1996
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.09 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.09 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(dds2inde)72 48 Q 348.04(x\(1L\) dds2inde)-.15 F
+(x\(1L\))-.15 E/F1 9/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0
+(dds2inde)108 96 Q 2.5(x\255t)-.15 G(ool to create an inde)-2.5 E
+(x\214le for the use of)-.15 E F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0
+SF(dds2index)108 124.8 Q F0([options])2.5 E F1(DESCRIPTION)72 141.6 Q F2
+(dds2index)108 153.6 Q F0 1.042(creates an inde)3.542 F 3.542<788c>-.15
+G 1.042(le that is required by the \214le e)-3.542 F 1.042
+(xtraction utility)-.15 F F2(dds2tar\(1\))3.542 E F0 6.041(.I)C 3.541
+(tw)-6.041 G 1.041(orks on)-3.641 F F2(tar)3.541 E F0(archi)108 165.6 Q
+-.15(ve)-.25 G 2.592(ss).15 G .092(tored on dds tape de)-2.592 F .092
+(vices \(D)-.25 F -1.11(AT)-.4 G 2.592(\). Since)1.11 F .092
+(the \214le structure of the tape archi)2.592 F -.15(ve)-.25 G 2.592(si)
+.15 G 2.592(su)-2.592 G .092(sed to e)-2.592 F .093(xtract the)-.15 F
+.37(\214les, the archi)108 177.6 R .67 -.15(ve m)-.25 H .37(ust be an)
+.15 F F2(uncompr)2.87 E .37(essed tar)-.18 F F0(archi)2.87 E -.15(ve)
+-.25 G 2.87(.B).15 G .37
+(ut compression by the transparent signal proces-)-2.87 F
+(sor of the tape de)108 189.6 Q(vice is allo)-.25 E(wed.)-.25 E .373
+(The inde)108 206.4 R 2.873(xc)-.15 G .373(reated by)-2.873 F F2
+(dds2index)2.873 E F0 .373(is written to)2.873 F/F3 10/Times-Italic@0 SF
+(stdout)2.873 E F0 .373(by def)2.873 F .374
+(ault and should normally be stored on hard disk)-.1 F(as)108 218.4 Q F3
+(inde)2.5 E(x\214le)-.2 E F0(for later use by)2.5 E F2(dds2tar\(1\))2.5
+E F0(.)A .487(The def)108 235.2 R .487(ault tape de)-.1 F .487
+(vice to read from is)-.25 F F3(/de)2.987 E(v/rmt0)-.15 E F0 2.987(,w)
+.47 G .487(hich may be o)-2.987 F -.15(ve)-.15 G .487
+(rridden with the en).15 F .486(vironment v)-.4 F(ariable)-.25 E F2 -.9
+(TA)108 247.2 S(PE).9 E F0 2.5(,w)C(hich in turn may be o)-2.5 E -.15
+(ve)-.15 G(rridden with the).15 E F2(-f)2.5 E F3(de)2.85 E(vice)-.15 E
+F0(option. The de)2.5 E(vice must be a SCSI tape de)-.25 E(vice.)-.25 E
+F1(OPTIONS)72 268.8 Q F2(-f)108 280.8 Q F3(de)2.85 E(vice\214le)-.15 E
+F0(de)144 292.8 Q(vice of the tape archi)-.25 E -.15(ve)-.25 G 2.5(.M)
+.15 G(ust be a character special \214le.)-2.5 E F2(-t)108 309.6 Q F3
+(inde)2.51 E(x\214le)-.2 E F0(write the inde)144 321.6 Q 2.5(xt)-.15 G
+(o)-2.5 E F3(inde)2.5 E(x\214le)-.2 E F0 2.5(,n).18 G(ot to)-2.5 E F3
+(stdout.)2.5 E F2(-z)108 338.4 Q F0(,)A F2(--compr)A(ess)-.18 E F0
+(write the inde)144 350.4 Q 2.5(xi)-.15 G 2.5(n\()-2.5 G
+(gzip\) compressed mode.)-2.5 E F2(--help)108 367.2 Q F0
+(print some screens of online help with e)11 E
+(xamples through a pager and e)-.15 E(xit immediatle)-.15 E -.65(y.)-.15
+G F1(OPTIONS y)72 384 Q(ou didn't r)-.225 E(eally need)-.162 E F2
+(-b, --block-size)108 396 Q F0(Set the maximal blocksize, dds2inde)144
+408 Q 2.5(xc)-.15 G(an handle.)-2.5 E F2(--z, --no-compr)108 436.8 Q
+(ess)-.18 E F0(Don')144 448.8 Q 2.5<748c>-.18 G(lter the archi)-2.5 E .3
+-.15(ve \214)-.25 H(le through gzip.).15 E F2(-v)108 465.6 Q F0(,)A F2
+(--v)A(erbose)-.1 E F0 -.15(ve)144 477.6 S(rbose mode. Print to).15 E F3
+(stderr)2.5 E F0(what is going on.)2.5 E F2(-h)108 494.4 Q F0(,)A F2
+(--hash-mode)A F0(Print a hash sign '#' to)144 506.4 Q F3(stderr)2.5 E
+F0(for each MB read from tape.)2.5 E F2(-V)108 523.2 Q F0(,)A F2(--v)A
+(ersion)-.1 E F0(Print the v)144 535.2 Q(ersion number of)-.15 E F2
+(dds2index)2.5 E F0(to)2.5 E F3(stderr)2.5 E F0(and e)2.5 E
+(xit immediately)-.15 E(.)-.65 E F1(EXAMPLES)72 552 Q F0
+(Example of getting the inde)108 564 Q 2.5(xf)-.15 G(rom the def)-2.5 E
+(ault tape /de)-.1 E(v/rmt0 and storing it in \214le archi)-.25 E -.15
+(ve)-.25 G(.idx:).15 E(dds2inde)144 580.8 Q 2.5(x-)-.15 G 2.5(v-)-2.5 G
+2.5(ta)-2.5 G(rchi)-2.5 E -.15(ve)-.25 G(.idx).15 E F1 -1.08(WA)72 597.6
+S(RNING)1.08 E F0 .63(This program can only read records \(tar is calli\
+ng them tape blocks\) up to 32 kbytes. A bigger b)108 609.6 R(uf)-.2 E
+.63(fer will)-.25 F(cause problems with the Linux de)108 621.6 Q
+(vice dri)-.25 E -.15(ve)-.25 G -.55(r.).15 G F1(ENVIR)72 638.4 Q
+(ONMENT)-.27 E F0(The en)108 650.4 Q(vironment v)-.4 E(ariable)-.25 E F2
+-.9(TA)2.5 G(PE).9 E F0 -.15(ove)2.5 G(rrides the def).15 E
+(ault tape de)-.1 E(vice /de)-.25 E(v/rmt0.)-.25 E F1(FILES)72 667.2 Q
+F0(/de)108 679.2 Q 28.86(v/rmt0 def)-.25 F(ault tape de)-.1 E
+(vice \214le. Must be a character special \214le.)-.25 E F1(SEE ALSO)72
+696 Q F0(dds2tar\(1\), mt\(1\), mt-dds\(1\), tar\(1\), gzip\(1\))108 708
+Q 220.25(2.4 1)299.75 768 R EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(dds2inde)72 48 Q 348.04(x\(1L\) dds2inde)-.15 F
+(x\(1L\))-.15 E/F1 9/Times-Bold@0 SF(HIST)72 84 Q(OR)-.162 E(Y)-.315 E
+F0(This program w)108 96 Q(as created as a tool for)-.1 E/F2 10
+/Times-Bold@0 SF(dds2tar\(1\))2.5 E F0(.)A F1 -.45(AU)72 124.8 S(THOR)
+.45 E F0(J"or)108 136.8 Q 3.029(gW)-.18 G .529
+(eule \(weule@cs.uni-duesseldorf.de\), Phone +49 211 751409.)-3.829 F
+.528(This softw)5.528 F .528(are is a)-.1 F -.25(va)-.2 G .528
+(ilable at ftp.uni-).25 F(duesseldorf.de:/pub/unix/apollo)108 148.8 Q
+220.25(2.4 2)299.75 768 R EP
+%%Trailer
+end
+%%EOF
diff --git a/dds2tar-test.sh b/dds2tar-test.sh
new file mode 100755 (executable)
index 0000000..d55ab8b
--- /dev/null
@@ -0,0 +1,153 @@
+#!/bin/sh
+make
+
+if test q$TAPE = q ; then export TAPE=/dev/nst0 ; fi
+case $TAPE in
+/dev/nst0|/dev/st0) V=`scsi_vendor tape 1` ;;
+/dev/nst1|/dev/st1) V=`scsi_vendor tape 2` ;;
+esac
+
+echo Tape vendor is $V
+echo =======================
+
+case $V in
+HP) B=32 ;;
+*) B=32 ;;
+esac
+
+X="--exclude=index*"
+
+echo $B
+echo $X
+
+#===================1==========================================================
+echo 'dds2tar-test  1>' make
+make
+
+#===================2==========================================================
+echo ' '
+echo 'dds2tar-test  2>' 'make of?'
+if test ! -x ./dds2tar ; then exit 1 ; fi
+
+#===================3==========================================================
+echo ' '
+echo 'dds2tar-test  3>' creating soft links
+ln -sf ./dds2tar ./dds2index
+ln -sf ./dds2tar ./mt-dds
+
+#===================4==========================================================
+echo ' '
+echo 'dds2tar-test  4>' creating soft and hard links
+ln -s dds2tar dds2tar-test-tape-link-soft
+ln dds2tar dds2tar-test-tape-link-hard
+
+#===================5==========================================================
+echo ' '
+echo 'dds2tar-test  5>' tar c .
+tar c $X .
+
+#===================6==========================================================
+echo ' '
+echo 'dds2tar-test  6>' tar -c --label dds2tar -b $B ... .
+tar --label dds2tar --record-file index-of-tar $X -R -v -c -b $B .
+
+I=`grep 'number of the file' index-of-tar | cut -c 38-43`
+if test q"$I" = q ; then I=1 ; fi 
+if test $I = 0 ; then exit 1 ; fi
+I=`expr $I - 1`
+echo file number of the archive written is $I
+if test "$I" = "" ; then exit 1 ; fi
+
+#===================7==========================================================
+echo ' '
+echo 'dds2tar-test  7>' tar -c . ...
+tar --record-file index-of-tar-v -v -R -v -c -b $B $X .
+
+#===================8==========================================================
+echo ' '
+echo 'dds2tar-test  8>' mt rewind \; mt fsf $I
+mt rewind ; mt fsf $I
+
+#===================9==========================================================
+echo ' '
+echo 'dds2tar-test  9>' mt-dds tell
+./mt-dds tell
+
+#==================10==========================================================
+echo ' '
+echo 'dds2tar-test 10>' mt-dds label
+./mt-dds label
+
+#==================11==========================================================
+echo ' '
+echo 'dds2tar-test 11>' mt-dds
+./mt-dds
+
+#==================12==========================================================
+echo ' '
+echo 'dds2tar-test 12>' dds2index
+./dds2index -t index-of-dds2index
+
+#==================13==========================================================
+echo ' '
+echo 'dds2tar-test 13>' find '*tape*' using index-of-tar
+./dds2tar -t index-of-tar '*tape*' | tar fvt -
+
+#==================14==========================================================
+echo ' '
+echo 'dds2tar-test 14>' find '*tape*' using index-of-tar-v
+./dds2tar -t index-of-tar-v '*tape*' | tar fvt -
+
+#==================15==========================================================
+echo ' '
+echo 'dds2tar-test 15>' find '*tape*' using index-of-dds2index
+./dds2tar -t index-of-dds2index '*tape*' | tar vft -
+
+#==================16==========================================================
+echo ' '
+echo 'dds2tar-test 16>' dds2tar -t index-of-tar --body Changes '|wc -c'
+./dds2tar -t index-of-tar --body Changes | wc -c
+ls -l Changes
+
+#==================17==========================================================
+echo 'dds2tar-test 17>' mt rewind \; mt fsf $I
+mt rewind ; mt fsf $I
+
+#==================18==========================================================
+echo ' '
+echo 'dds2tar-test 18>mt-dds'
+mt-dds
+
+#==================19==========================================================
+echo ' '
+echo 'dds2tar-test 19> mt-dds tell >'index-of-tar-t
+mt-dds tell >index-of-tar-t
+
+#==================20==========================================================
+echo ' '
+echo 'dds2tar-test 20> tar tR >>' index-of-tar-t
+tar tR >> index-of-tar-t
+
+#==================21==========================================================
+echo ' '
+echo 'dds2tar-test 21>' grep -v "'loc        '" '< index-of-tar-t > index-of-tar-t2'
+grep -v 'loc        ' < index-of-tar-t > index-of-tar-t2
+
+#==================22==========================================================
+echo 'dds2tar-test 22>' mt rewind \; mt fsf $I
+mt rewind ; mt fsf $I
+
+#==================23==========================================================
+echo 'dds2tar-test 23>' find '*tape*' using index-of-tar-t2 and mt-dds
+echo 'dda2tar-test 23>' ./dds2tar '`mt-dds`' -t index-of-tar-t2 "'*tape*' | tar bvft 1 -"
+./dds2tar `mt-dds` -v -t index-of-tar-t2 '*tape*' | tar bvft 1 -
+
+#==================24==========================================================
+echo 'dds2tar-test 24>' mt rewind \; mt fsf $I
+mt rewind ; mt fsf $I
+
+#==================25==========================================================
+echo 'dds2tar-test 25>' removing links
+/bin/rm dds2tar-test-tape-link-soft
+/bin/rm dds2tar-test-tape-link-hard
+
diff --git a/dds2tar.c b/dds2tar.c
new file mode 100644 (file)
index 0000000..3ca0a66
--- /dev/null
+++ b/dds2tar.c
@@ -0,0 +1,846 @@
+/*
+    dds2tar  Digital-Data-Storage Extract Tool
+
+             This tool makes use of the fast seek command of DAT devices.
+             Files from a selected file archive can be extracted within
+             one minute.
+
+             J"org Weule                     weule@cs.uni-duesseldorf.de
+                                             Fon: +49 211 751409
+
+----------------------------------------------------------------------------
+
+                              LICENSE
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published
+    by the Free Software Foundation; either version 1, or (at your option)
+    any        later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+----------------------------------------------------------------------------
+
+    To anyone in Germany I declare the following:
+
+    !  Ich werde gegen jede Verbreitung dieser Software rechtlich        !
+    !  vorgehen, welche die Lizenzbestimmungen nicht einh"alt.           !
+
+       Wie f"ur jede andere Software gilt auch hier:
+       Schon mit dem Kopieren oder Benutzen von Teilen dieser Software
+       werden die Lizenzbedingungen stillschweigend akzeptiert. Lesen Sie
+       also die Lizenzbedingungen sorgf"altig! Unkenntnis sch"utzt nicht
+       vor Strafe.
+
+*/
+
+/*-------------------------------------------------------------------------*/
+
+#include <stdlib.h>            /* getenv() */
+#include <stdio.h>
+#include <string.h>            /* strcmp() strlen() strstr() */
+#include <sys/types.h>         /* open() stat() */
+#include <sys/stat.h>          /* stat() */
+#include <fcntl.h>             /* open() */
+#include <unistd.h>            /* open() */
+#include <time.h>              /* ctime() */
+
+#include "dds2tar.h"
+#include "dds_tape.h"
+#include "zf-cre-open.h"
+
+char vendor[9] = "\0\0\0\0\0\0\0\0\0" ;
+int vid; /* vendor id */
+
+/*-------------------------------------------------------------------------*/
+
+static const char help_text_dds2index[] =
+"This is dds2index, a tool for fast tape access.\n"
+"Choose one of the following\n"
+"-t,--table-of-contents F  get file location from file F\n"
+"-z,--compress           filter location file through gzip\n"
+"--z,--no-compress       don't filter location file through gzip\n"
+"-f,--device F           read the archive from device F\n"
+"-b,--block-size #       set block size (non HP/SONY)\n"
+"-B,--Block-size #       set block size (HP or SONY)\n"
+"-q,--quick              don't extract parent directories from tape\n"
+"-v,--verbose            verbose mode\n"
+"--hash-mode             hash mode\n"
+"--force                 force nochk\n"
+"--help                  get help\n"
+"-V,--version            print version number\n"
+"\n"
+"Environment:\n"
+"TAPE                    specifies the tape device\n"
+"DDS2TAR=[--compress] [-z] [-s #] [-b #]\n"
+"                        set some defaults\n"
+       ;
+
+static const char help_text_dds2tar[] =
+"This is dds2tar, a tool for fast tape access.\n"
+"Usage: dds2tar [options... ] -t index [pathname ...]  | tar -f - ...\n"
+"\n"
+"dds2tar is a tool to read some tar-records from tape and write them\n"
+"as a tar archive to stdout. You have to use tar to extract the\n"
+"selected files. The index can either be created by dds2tar or tar.\n"
+"\n"
+"Choose one of the following\n"
+"-t,--table-of-contents F  get file location from file F\n"
+"-z,--compress           filter location file through gzip\n"
+"--z,--no-compress       don't filter location file through gzip\n"
+"-f,--device F           read the archive from device F\n"
+"-o,--output F           write output to archive file\n"
+"-b,--block-size #       set block size (non HP/SONY)\n"
+"-B,--Block-size #       set block size (HP or SONY)\n"
+"-s,--first_block #      set number of the first block\n"
+"--body                  print only the contents of the first file an quit\n"
+"-v,--verbose            verbose mode\n"
+"--help                  get help\n"
+"-V,--version            print version number\n"
+"\n"
+"Environment:\n"
+"TAPE                    specifies the tape device\n"
+"DDS2TAR=[--compress] [-z] [-s #] [-b #]\n"
+"                        set some defaults\n"
+       ;
+
+static const char help_text_mt_dds[] =
+"This is mt-dds, a tool to control the dds-device.\n"
+"Usage: mt-dds [-f device] <action>\n"
+"\n"
+"Choose one or none of the following actions:\n"
+#ifdef HPDAT
+"comp-on      set compression mode on\n"
+"comp-off     set compression mode off\n"
+"comp-query   query compression mode\n"
+"comp-log     print compression log page\n"
+#endif
+"-b           set the buffer size\n"
+"blksize      print the block size of the archive with format\n"
+"tell         print current location and blocksize\n"
+"where        print current location\n"
+"label        print the label of the current archive\n"
+"             if it begins at the current position\n"
+"filename     print the filename of the current record\n"
+"             if a header record is found at the current position\n"
+"ts           print the timestamp of the current archive\n"
+"date         print the date of the current archive\n"
+"scsi2logical select mode scsi2logical first\n"
+"             if it begins at the current position\n"
+"date <timestamp> convert the stamp to a string\n"
+       ;
+
+static const char help_text_dds_dd[] =
+"This is dds-dd, a tool to read the dds-device.\n"
+"Usage: dds-dd` [-f device] | tar -f - -[x|t] ... \n";
+
+/*-------------------------------------------------------------------------*/
+
+static const char version[] =
+"Version " VERSION " -- last change 1994 Dez 22." ;
+
+/*-------------------------------------------------------------------------*/
+
+/* This is the source for dds2tar, dds2index and mt-dds. The program will
+   use the variable pg to decide witch version is running. The default
+   can be set in the Makefile and is overwritten by the value of argv[0].
+   If you give --dds2tar, --dds2index or --mt-dds as an option, the
+   program will run instead of these.
+*/
+
+#define DDS2TAR name_dds2tar
+static char const name_dds2tar[] = "dds2tar";
+
+#define DDS2INDEX name_dds2index
+static char const name_dds2index[] = "dds2index";
+
+#define MTDDS name_mtdds
+static char const name_mtdds[] = "mt-dds";
+
+#define DDS_DD name_dds_dd
+static char const name_dds_dd[] = "dds-dd";
+
+
+#if ( PROGRAM == DDS2TAR )
+char const *pg = name_dds2tar;
+char const *help_text = help_text_dds2tar;
+
+#elif ( PROGRAM == DDS2INDEX )
+char const *pg = name_dds2index;
+char const *help_text = help_text_dds2index;
+
+#elif ( PROGRAM == DDS2TAR )
+char const *pg = name_mtdds;
+char const *help_text = help_text_mt_dds;
+
+#elif ( PROGRAM == DDS_DD )
+char const *pg = name_dds_dd;
+char const *help_text = help_text_dds_dd;
+
+#else
+char const *pg = name_dds2tar;
+char   *help_text = help_text_dds2tar;
+
+#endif
+
+#define LOCATION 1
+#define EXTRACT 2
+
+/*-------------------------------------------------------------------------*/
+
+char const dds_old_headline[] =
+"magic record blk:     size name\n";
+
+char const dds_old_index_format[] =
+"%6s%7d%3d:%9d %s\n";
+
+/* magic blkno recno: size name */
+
+char const dds_old_index_scan_format[] =
+"%6c%7d%3d:%9d\n";
+
+char const dds_headline[] =
+"magic  record blk:     size name\n";
+
+char const dds_index_format[] =
+"%6s%7d%4d:%9d %s\n";
+
+/* magic blkno recno: size name */
+
+char const dds_index_scan_format[] =
+"%6c%7d%4d:%9d\n";
+
+/* magic blkno recno: size name */
+
+char const dds_loctext[] =
+"first block number is %d\n"
+"block size is %d\n" "block length is %d\n";
+
+char const dds_locline1[] =
+"loc             number of the first block is %d\n";
+
+char const dds_locline2[] =
+"loc             block length is %d bytes = %d * 512 bytes\n";
+
+/* to handle long link and long file names */
+int long_name_len = 0 ;
+char long_name[MAXPATHLEN<<2] = { '\0' };
+
+int
+rt_loc_line(void)
+{
+#define strneq(a,b,n) strncmp(a,b,n)==0
+
+       if ( strneq(cur_line, dds_locline1, 45) ) {
+               tar_fb = atoi(cur_line + 45);
+       } else
+       if ( strneq(cur_line, "first block number is", 21) ) {
+               tar_fb = atoi(cur_line + 21);
+       } else
+       if ( strneq(cur_line, dds_locline2, 31) ) {
+               tar_n = atoi(cur_line + 31);
+               tar_bs = tar_n >> 9;
+       } else
+       if ( strneq(cur_line, "block size is", 13) ) {
+               tar_bs = atoi(cur_line + 13);
+               tar_n = tar_bs << 9;
+       } else
+       if ( strneq(cur_line, "block length is", 15) ) {
+               tar_n = atoi(cur_line + 15) ;
+               tar_bs = tar_n >> 9 ;
+       } else {
+               return 1;
+       }
+
+       if ( verbose ) fprintf(stderr,
+               "block length is %d = %d * 512 \n", tar_n, tar_bs );
+
+#undef strneq
+
+       if ( buf_n < tar_n ) {
+               cur_block = realloc ( cur_block , buf_n = tar_n );
+               if ( cur_block == NULL ) {
+                       fprintf(stderr, "%s: No memory available.\n", pg);
+                       exit(2);
+               }
+       }
+       return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+int     verbose = 0;
+int     hash_mode = 0;
+int     list_only = 0;         /* print only the matched names */
+int    quick_mode = 0;         /* don't extract parent directories also */
+int     device;                        /* file number of the device */
+int    write_body = 0 ;        /* write only the body of the first file */
+int    get_label = 0 ;         /* get the label of the archive */
+int    get_filename = 0 ;      /* get the filename of the current record */
+int    get_blocksize = 0 ;     /* get the blocksize of the current record */
+int    get_timestamp = 0 ;     /* get the timestamp of the archive */
+int    get_date = 0 ;          /* get the date of the archive */
+int    get_fileno = 0 ;        /* get the number of the current */
+int    force_nochk = 0 ;       /* force tape read, no check of headers */
+
+/* file io */
+FILE   *index_fp = NULL;
+
+/* archive location as set by arguments or index file */
+int     tar_fb = 0;            /* first block of the archive */
+int     tar_bs = 20;           /* block size in records of 512 bytes */
+int     tar_n = 10240;         /* block length in bytes */
+
+/* archive buffer and location as set by tape access */
+tar_record *cur_block;
+int     cur_blkno = -1;
+int    next_blkno = -1 ;
+int     cur_bs;
+int     cur_n;
+int    buf_n = ST_BUFFER_BLOCKS << 10 ;
+
+/* line buffer to scan the index file */
+char   *cur_line;
+
+/*-------------------------------------------------------------------------*/
+
+/********
+       *  input: name of the device ( e.g. /dev/nst0, /dev/nrmt0 or NULL )
+       *         open mode of the device ( e.g. O_RDONLY or O_WRONLY )
+       *         verbose flag to indicate the logging mode (integer)
+       * output: channel number ( integer ) for use with 'read()' or 'write()'
+        *
+        * side effects: none
+       *
+       **********************************************************************/
+
+static int
+open_device(char const *pathname, int const open_mode)
+{
+       int     fd;
+       int     i = 1;
+       char   const *p = "next try to open the tape %s\n";
+
+       {
+               int i ;
+               struct stat s ;
+               FILE *f ;
+               char cmd[100];
+               i = stat(pathname,&s);
+               if ( i < 0 ) perror("dds2tar"),exit(1);
+               sprintf(cmd,"scsi_vendor tape %d",(int)(s.st_rdev&0x7f)+1);
+               f = popen(cmd,"r");
+               fread(vendor,1,8,f);
+               fclose(f);
+               for ( i = 0 ; i < 8 ; i++ )
+                       ( vendor[i] < 0x20 ) && ( vendor[i] = '\0' ) ;
+               if ( !strcmp(vendor,"HP") ) vid = HP ;
+               if ( !strcmp(vendor,"SONY") ) vid = SONY ;
+               if ( !strcmp(vendor,"ARCHIVE") ) vid = ARCHIVE ;
+               if ( !strcmp(vendor,"SEGATE") ) vid = SEGATE ;
+               if ( !strcmp(vendor,"EXABYTE") ) vid = EXABYTE ;
+       }
+               
+       do {
+               if ((fd = open(pathname, open_mode)) >= 0)
+                       break;
+               sleep(2);
+               if (verbose)
+                       fprintf(stderr, p, pathname);
+       } while ((++i) <= 15);
+       if (fd < 0) {
+               perror("tape busy?");
+               exit(1);
+       } /* else dds_has_partitions(fd); */
+       return fd;
+}
+
+/*-------------------------------------------------------------------------*/
+int
+strprefix(char**s,char*p,char*q){
+       while ( p != 0 ) {
+               char *t = *s ; while (( *p != 0 ) && ( *p == *t )) p++ , t++ ;
+               if ( *p == 0 ) { *s = t ; return 1 ; }
+               p = q ; q = NULL ;
+       } return 0 ;
+}
+/*-------------------------------------------------------------------------*/
+
+/*
+ * dds2tar
+ */
+int
+main(int argc, char *const *argv)
+{
+
+#ifndef DEVICE
+#define DEVICE "/dev/rmt0"
+#endif
+
+       int     density = 0 ;
+       int     n = 1;
+       int     l = strlen(argv[0]);
+       int     compressed_mode = T_MODE;
+       char   *p;
+       int     child_proc = -1;/* child not running */
+       char const *index_file = NULL;
+       int     print_location = 0;
+       int     print_blksize = 0;
+       int     mt_action = DDSCM_NULL; /* turn compression on/off */
+       int     mode = 0;       /* mode of dds2tar */
+       char const *const *pattern_list = NULL;
+       char const *device_name = DEVICE;
+
+       if ((p = getenv("TAPE")) != NULL)
+               device_name = p;
+
+       if (!strcmp(argv[0] + l - 7, "dds2tar")) {
+               pg = DDS2TAR;
+               help_text = help_text_dds2tar;
+       }
+       if (!strcmp(argv[0] + l - 9, "dds2index")) {
+               pg = DDS2INDEX;
+               help_text = help_text_dds2index;
+       }
+       if (!strcmp(argv[0] + l - 6, "mt-dds")) {
+               pg = MTDDS;
+               help_text = help_text_mt_dds;
+       }
+       if (!strcmp(argv[0] + l - 6, "dds-dd")) {
+               pg = DDS_DD;
+               help_text = help_text_dds_dd;
+       }
+
+       /*
+        * Scanning the environment.
+        */
+       p = getenv("DDS2TAR");
+       while (p != NULL) {
+               int count = 0 ;
+               if (*p == ' ') p++;
+               if ( *p == '\0' ) p = NULL ;
+               else if (strprefix(&p, "-z","--compress")) {
+                       compressed_mode = C_MODE;
+               } else if (strprefix(&p, "--first-block ","-s")) {
+                       sscanf(p, "%d%n", &tar_fb, &count);
+                       p += count;
+               } else if (strprefix(&p, "--block-size ","-b ")){
+                       sscanf(p, "%d%n", &tar_bs, &count);
+                       tar_n = tar_bs * 512 ;
+                       buf_n = tar_n ;
+                       p += count;
+               } else if (strprefix(&p, "--Block-size ","-B ")){
+                       sscanf(p, "%d%n", &tar_bs, &count);
+                       tar_n = tar_bs * 512 ;
+                       buf_n = tar_n ;
+                       p += count;
+                       density = tar_n ;
+               } else
+                       p = NULL;
+       }
+
+       /*
+        * scan arguments
+        */
+       while (n < argc) {
+
+               /*
+                * Macros to test arguments ...
+                */
+
+#define T1(s)        if((!strcmp(argv[n],(s))))
+#define T(s)    else if((!strcmp(argv[n],(s))))
+#define TT(s,t) else if((!strcmp(argv[n],(s)))||(!strcmp(argv[n],(t))))
+#define ELSE    else
+#define ELSEIF(s) else if(s)
+
+               /*
+                * Now scanning the arguments ...
+                */
+
+               T1("-0") {
+                       fprintf(stdout, "dds2tar: %s\n", argv[0]);
+                       exit(0);
+               }
+
+               /*
+                * misc
+                */
+               T("--help") {
+                       fprintf(stdout, help_text);
+                       exit(0);
+               }
+               TT("--version", "-V") {
+                       fprintf(stdout, "%s: %s\n", pg, version);
+                       exit(0);
+               }
+
+               /*
+                * Some more options ...
+                */
+               TT("--verbose", "-v") verbose = 1;
+               T("--hash-mode") hash_mode = 1;
+               T("--force") force_nochk = 1;
+
+               /*
+                * device name
+                */
+               T("-f") device_name = argv[++n];
+
+               /*
+                * index file
+                */
+               TT("-z", "--compress") compressed_mode = C_MODE;
+               TT("--z", "--no-compress") compressed_mode = T_MODE;
+               TT("-t", "--table-of-contents") {
+                       index_file = argv[++n];
+                       /*
+                        * The format of the index is checked by the program.
+                        */
+               }
+
+               /*
+                * Location of the file
+                */
+               TT("-s", "--first-block") {
+                       tar_fb = atoi(argv[++n]);
+               }
+               TT("-b", "--block-size") {
+                       tar_bs = atoi(argv[++n]);
+                       tar_n = tar_bs * 512 ;
+                       buf_n = tar_n ;
+               }
+               TT("-B", "--Block-size") {
+                       tar_bs = atoi(argv[++n]);
+                       tar_n = tar_bs * 512 ;
+                       buf_n = tar_n ;
+                       density = tar_n ;
+               }
+               TT("-m", "--buffer-size") {
+                       fprintf(stderr,"buffer size is %d records, %d bytes\n",
+                               buf_n>>9,buf_n);
+                       exit(0);
+               }
+
+               ELSEIF(pg == DDS2TAR) {
+                       /*
+                        * Mode of the program.
+                        *
+                        * If you install dds2tar as mt-dds, the program will
+                        * act as mt-dds. Since for some operations you need
+                        * root permissions on mt-dds, it would not be a good
+                        * idea to let the user switch to dds2index or dds2tar
+                        * in this case.
+                        */
+
+                       T1("--dds2index") {
+                               pg = DDS2INDEX;
+
+                               help_text = help_text_dds2index;
+                       }
+                       T("--mt-dds") {
+                               pg = MTDDS;
+                               help_text = help_text_mt_dds;
+                       }
+                       T("--dds-dd") {
+                               pg = DDS_DD;
+                               help_text = help_text_dds_dd;
+                       }
+                       /*
+                        * Mode of extraction ...
+                        *
+                        * The location list an experimental mode.
+                        */
+#ifdef EXP_STUFF
+                       T("--location-list") {
+                               pattern_list = argv + n + 1;
+                               mode = LOCATION;
+                               break;
+                       }
+#endif
+                       /*
+                        * Select a file for the output.
+                        *
+                        * Since mt-dds may be run as root, we write on screen
+                        * in this case. Writing to a file is supported for
+                        * dds2tar.
+                        */
+                       TT("-o", "--output") {
+                               reopen(1, argv[++n], O_WRONLY | O_CREAT, 0660);
+                       }
+
+                       /*
+                        * Do not read anything from tape.
+                        */
+                       TT("-l", "--list") {
+                               list_only = 1;
+                               if (verbose)
+                                       fputs("--list\n", stderr);
+                       }
+                       /*
+                        * Write only the body of the file.
+                        */
+                       T("--body"){
+                               write_body = 1 ;
+                       }
+
+                       /*
+                        * Don't extract the parent directories from the tape.
+                        */
+                       TT("-q","--quick"){
+                               quick_mode = 1 ;
+                       }
+                       /*
+                        * Pipe the output to tar -x.
+                        *
+                        * This is for testing only.
+                        */
+                       T("--test") {
+                               static char const *const a[5] =
+                               {
+                                       "/bin/tar", "tfb", "-", "1", NULL
+                               };
+
+                               child_proc = creopen(1, 0, a[0], a);
+                       }
+                       T("--test-verbose") {
+                               static char const *const a[5] =
+                               {
+                                       "/bin/tar", "tfbv", "-", "1", NULL
+                               };
+
+                               child_proc = creopen(1, 0, a[0], a);
+                       }
+                       T("--extract") {
+                               static char const *const a[5] =
+                               {
+                                       "/bin/tar", "xfb", "-", "1", NULL
+                               };
+
+                               child_proc = creopen(1, 0, a[0], a);
+                       }
+                       ELSE {
+                               {
+                                       char*const*p = argv+n ;
+                                       while (*p) dds_unquote(*p++) ;
+                               }
+                               pattern_list = (const char*const*)argv + n;
+                               if (verbose)
+                                       fprintf(stderr,
+                                               "first pattern is '%s'\n",
+                                               *pattern_list
+                                               );
+                               mode = EXTRACT;
+                               break;
+                       }
+               }
+
+               ELSEIF(pg == MTDDS) {
+                       /*
+                        * Tape actions ...
+                        */
+                       T1("tell") print_location = 1;
+                       T("label") get_label = 1 ;
+                       T("filename") get_filename = 1 ;
+                       T("bs") get_blocksize = 1 ;
+                       T("date") {
+                               get_date = 1 ;
+                               if ( argc > 2 ) {
+                                       int j = atoi(argv[2]);
+                                       fputs(ctime((time_t*)&j),stdout);
+                                       exit(0);
+                               }
+                       }
+                       T("ts") get_timestamp = 1 ;
+                       T("blksize") print_blksize = 1 ;
+#ifdef HPDAT
+#define R(c) if ( 0 != geteuid() ) { fprintf(stderr,\
+"You have to be root to do this : %s\n",c);exit(1);}
+                       T("comp-on") {
+                               R("comp-on");
+                               mt_action = DDSCM_ON;
+                       }
+                       T("comp-off") {
+                               R("comp-off");
+                               mt_action = DDSCM_OFF;
+                       }
+                       T("comp-query") {
+                               R("comp-query");
+                               mt_action = DDSCM_QUERY;
+                       }
+                       T("comp-log") {
+                               R("comp-log");
+                               mt_action = DDSCM_LOG;
+                       }
+                       T("load") {
+                               R("comp-load");
+                               mt_action = DDSCM_LOAD;
+                       }
+                       T("unload") {
+                               R("comp-unload");
+                               mt_action = DDSCM_UNLOAD;
+                       }
+                       T("where") {
+                               mt_action = DDSCM_WHERE;
+                       }
+                       /*
+                        * Set mode scsi2logical first
+                        */
+                       T("scsi2logical"){
+                               mt_action = DDSCM_LOGICAL;
+                       }
+
+#endif
+#ifdef EXP_STUFF
+                       /*
+                * tar-dds will handle the arguments in a very different way.
+                */
+               }
+               ELSEIF(pg == TAR_DDS) {
+
+                       break;
+#endif
+               }
+               /*
+                * Next argument ...
+                */
+               n++;
+       }
+
+       cur_block = malloc(buf_n);
+       cur_line = malloc(MAXPATHLEN<<2);
+       if (cur_block == NULL || cur_line == NULL) {
+               fprintf(stderr, "%s: No memory available.\n", pg);
+               exit(2);
+       }
+       /*
+        * Switch the program mode ... dds2tar, dds2index or mt-dds ...
+        */
+       /*---------------------MT-DDS--------------------------------*/
+       if (pg == MTDDS) {
+#ifdef HPDAT
+               /*
+                * Is setting of compression mode or log page selected ?
+                *
+                * I think you have to run this as root.
+                */
+               if (mt_action != DDSCM_NULL) {
+                       device = open_device(device_name, O_WRONLY);
+                       if ( mt_action == DDSCM_LOGICAL )
+                               dds_scsi2logical();
+                       else
+                       if ( mt_action == DDSCM_WHERE ) {
+                               tar_fb = dds_getpos(device);
+                               printf(" -s %d \n", tar_fb);
+                               close(device);
+                               return 0;
+                       } else
+                               set_compression_mode(device, mt_action);
+               } else
+#endif
+               /*
+                * Print the current position (tree lines).
+                */
+               {
+                       device = open_device(device_name, O_RDONLY);
+                       if ( vid == HP ){
+                               tar_fb = dds_getpos(device);
+                               dds_read_next_block();
+                               /* dds_seek(device, tar_fb); */
+                               dds_bsr();
+                       } else {
+                               tar_fb = dds_getpos(device);
+                               cur_n = tar_n ;
+                       }
+                       tar_bs = cur_n >> 9;
+                       if (( get_label || get_timestamp ||
+                               get_date || get_filename ) &&
+                               ( dds_is_tar_header_record(cur_block) != 0 )) {
+                               if ( cur_block->hdr.linkflag == 'V' ) {
+                                       int i , j = 0 ;
+                                       char*p=cur_block->hdr.mtime ;
+                                       for ( i = 0 ; i < 12 ; i++ ) {
+                                               if ((p[i]>='0')&&(p[i]<='7')) {
+                                                       j <<= 3 ;
+                                                       j += p[i] - '0' ;
+                                               }
+                                       }
+                                       if ( get_label )
+                                               puts(cur_block->hdr.name);
+                                       else if ( get_timestamp ){
+                                               printf("%d\n",j);
+                                       } else /* get_date */ {
+                                               fputs(ctime((time_t*)&j),stdout);
+                                       }
+                               } else
+                               if ( get_filename ) puts(cur_block->hdr.name);
+                       } else
+                       if (print_location != 0) {
+                               printf(dds_loctext, tar_fb, tar_bs, cur_n);
+                       } else
+                       if ( print_blksize != 0 ) {
+                               printf("%d\n",tar_bs);
+                       } else {
+                               /*
+                                * Print the current position (one line).
+                                */
+                               printf(" -s %d -b %d \n", tar_fb, tar_bs);
+                       }
+               }
+               close(device);
+               /*---------------------DDS2TAR-------------------------------*/
+       } else if (pg == DDS2TAR) {
+
+               if (pattern_list == NULL)
+                       return 0;
+               if (list_only != 1) {
+                       device = open_device(device_name, O_RDONLY);
+
+                       if ( density ) dds_set_bs(density);
+               }
+               index_fp = zfopen(index_file, compressed_mode, "r");
+               switch (mode) {
+#ifdef EXP_STUFF
+               case LOCATION:
+                       extract_loc(pattern_list);
+                       break;
+#endif
+               case EXTRACT:
+                       dds_cmp(pattern_list);
+                       break;
+               default:
+                       fprintf(stderr, "nothing to do ? Try --help\n");
+               }
+               if (list_only != 1)
+                       close(device);
+               if (child_proc != -1)
+                       cclose(1);
+               /*---------------------DDS2INDEX-----------------------------*/
+       } else if (pg == DDS2INDEX) {
+               device = open_device(device_name, O_RDONLY);
+               if ( density ) dds_set_bs(density);
+               index_fp = zfopen(index_file, compressed_mode, "w");
+               dds_index();
+               close(device);
+               /*-----------------------------------------------------------*/
+       } else if ( pg == DDS_DD ) {
+               device = open_device(device_name, O_RDONLY);
+               if ( density ) dds_set_bs(density);
+               if ( verbose ) fprintf(stderr,"dds-dd ...\n");
+               while ( dds_read_next_block() , cur_n )
+                       fwrite(cur_block,1,cur_n,stdout);
+       } else {
+               fprintf(stderr, "no program mode \n");
+               /*-----------------------------------------------------------*/
+       }
+       return 0;
+}
+
diff --git a/dds2tar.h b/dds2tar.h
new file mode 100644 (file)
index 0000000..79bf12b
--- /dev/null
+++ b/dds2tar.h
@@ -0,0 +1,111 @@
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+/*
+ * Please change the value ST_BUFFER_BLOCKS at the top of the Makefile
+ * on error with these lines.
+ */
+#if defined ST_BUFFER_BLOCKS && ST_BUFFER_BLOCKS == 0
+#undef ST_BUFFER_BLOCKS
+#include "/usr/src/linux/drivers/scsi/st_options.h"
+#endif
+
+#ifndef ST_BUFFER_BLOCKS
+#define ST_BUFFER_BLOCKS 32
+#endif
+
+#include <sys/param.h>
+
+#define UNKNOWN 0
+#define HP 1
+#define SONY 1
+#define SEGATE 2
+#define ARCHIVE 2
+#define EXABYTE 2
+
+extern const char dds_headline[];
+extern const char dds_index_format[];
+extern const char dds_index_scan_format[];
+extern const char dds_old_headline[];
+extern const char dds_old_index_format[];
+extern const char dds_old_index_scan_format[];
+extern const char dds_loctext[];
+extern const char dds_locline1[];
+extern const char dds_locline2[];
+extern int dds_set_bs(int);
+extern char vendor[9];
+extern int vid; /* vendor ID */
+
+/*
+ * It's faster to read some records than to skip over them,
+ * if the number is smaller then DONT_SKIP.
+ * I really don't know the right number here.
+ */
+#define DONT_SKIP ((cur_n>0)?((int)(1024/cur_n)):((int)(1024/buf_n)))
+
+typedef union {
+       char    chrptr[512];
+       struct {
+               char    name[100];
+               char    dummy1[24];
+               char    size[12];
+               char    mtime[12];
+               char    dummy2[8];
+               char    linkflag;
+               char    dummy3[100];
+               char    magic[8];
+       }
+       hdr;
+}
+
+tar_record;
+
+#define LF_LONGLINK 'K'
+#define LF_LONGNAME 'L'
+
+extern int tar_fb;
+extern int tar_bs;
+extern int tar_n;
+
+extern tar_record *cur_block;
+extern int cur_blkno;
+extern int next_blkno;
+extern int cur_n;
+extern int cur_bs;
+extern int buf_n;
+extern int force_nochk;
+
+extern char *cur_line;
+
+extern int hash_mode;
+extern int quick_mode;
+extern int device;
+extern int verbose;
+extern int list_only;
+extern FILE *index_fp;
+extern int write_body;
+extern int long_name_len;
+extern char long_name[MAXPATHLEN<<2];
+
+extern char* dds_quote(char*str);
+extern int dds_unquote(char*str);
+
+extern int dds_index(void);
+extern int dds_cmp(char const *const *pattern);
+extern int rt_line(
+                         int *const ptr_blkno,
+                         int *const ptr_recno,
+                         int *const ptr_size,
+                         char **const ptr_name
+);
+extern int rt_loc_line(void);
+extern int extract_loc(char const *const *);
+
+#ifdef  EXP_STUFF
+extern int tar_dds(int const, char const *const *const);
+
+#endif
+
+extern int dds_is_tar_header_record(tar_record*const);
diff --git a/dds2tar.lsm b/dds2tar.lsm
new file mode 100644 (file)
index 0000000..b7375bc
--- /dev/null
@@ -0,0 +1,26 @@
+Begin3
+Title:         Tool to maintain tar tape archives and control compression.
+Version:       VERSION
+Description:   Once you have recorded the record number of each file of
+               a tar scsi-tape archive, you are able to find and extract these
+               files very fast. If you have a DAT drive, you can extract every
+               small file from a 2GB tape within 40 seconds.
+               tar2tar is included to change the pathnames inside a tar-archive.
+Author:        weule@7b5.de (J"org Weule)
+Maintained-by: weule@7b5.de
+Primary-Site:  sunsite.unc.edu:/pub/linux/system/backup
+                         LENGTH dds2tar-VERSION.tar.gz
+Alternate-Site:www.eulesoft.de
+                         LENGTH dds2tar-VERSION.tar.gz
+Platforms:     Linux and HP (because of the TELL and SEEK command)
+               HP is not well supported.
+               SCSI-Tape drive
+Copying-Policy:GPL
+Keywords:      tape archives  , tar
+Comment:       The software is only convenient, if your tape supports a fast
+               positioning command.
+               Added code (mt-dds) to change the compression mode of HP-DAT.
+               tar2tar will work on every computer with ANSI-C.
+               A patch to GNU-tar is included to add the option --record-file.
+End
+
diff --git a/dds2tar.man b/dds2tar.man
new file mode 100644 (file)
index 0000000..af262f8
--- /dev/null
@@ -0,0 +1,363 @@
+.TH dds2tar 1L 2.3 \" -*- nroff -*-
+.SH NAME
+dds2tar \- tool for fast tape access
+.SH SYNOPSIS
+.B dds2tar
+[
+.B -f
+.I device
+] [
+.B -t
+.I indexfile
+] [options]
+.I string ...
+.PP
+.SH DESCRIPTION
+.B dds2tar
+uses an index to find the files with record seek (a fast
+operation of DAT devices).
+Since the file structure of the tape archives is
+used to extract the files, the archive has to be created by
+.BR tar ,
+compressed only by (the transparent
+signal processor of) the device.
+So you can step through the archive
+very quickly and extract files.
+The index may be created using
+.BR dds2index
+or
+.BR tar -vRt
+and is normally stored as a file on your hard disk.
+.PP
+A tar archive is a sequence of blocks (e.g. 10240 bytes by default),
+each containing the same number (20 by default) of records, 512 byte each.
+.B dds2tar
+reads the tape and writes the tar records of the
+specified files (that means the header record and the data records of each
+selected file)
+to stdout.
+You may pipe the
+.B dds2tar
+output to the stdin of
+.I tar -xvvf -
+to restore the files to your disk.
+(See
+.B EXAMPLES
+below.)
+Before a file is extracted, 
+the records of parent directories of the file are also written to stdout.
+.PP
+The index of the archive should contain enough information
+to compute the number of the block containing the header of each selected
+file.
+.B dds2index
+will give such a table,
+.B tar -Rvt
+e.g. will not (only record numbers are listed).
+A patch for
+.B GNU tar-1.12
+is available, adding the option
+.B --record-file.
+Alternatively there are some tricks to get the missing
+information.
+.PP
+The strings are regular expressions to select the files.
+The matching algorithm is the one from GNU tar. If the option
+.B -l
+is given, the matched file names are printed to stdout (You may not pipe
+this list of pathnames to tar!).
+.PP
+The default device is
+.IR /dev/tape ,
+which may be overridden with the environment variable
+.BR TAPE ,
+which in turn may be overridden with the
+.BI -f\  device
+option. The device must be a SCSI tape device.
+.SH OPTIONS
+.BI -f\  devicefile
+Device of the tape archive. Must be a SCSI tape device.
+.TP
+.BI -t\  indexfile
+Specifies the index file (default is stdin).
+.TP
+.BI -s\ #
+Set the number of the first tape block of the archive. This option is
+useful only if the index file contains the verbose output of
+.B tar -Rvt.
+Any information about the first block
+inside the index file will be overridden by this option.
+If no information is available, the archive has to be the first file of
+the tape. If you have positioned your tape at the first block of the archive,
+you can use
+.IP
+.B dds2tar `mt-dds` -t index ... | tar -f - ...
+.IP
+to complete the information of the output of
+.B tar -Rvt
+stored in the
+index file.
+.TP
+.BI -b\ #
+Set the blocksize of the archive (tar -b #). This option is
+useful only if the index file contains the verbose output of tar (or if
+you have problems with the size of the internal buffer of dds2tar).
+Any information about the blocksize
+inside the index file will be overridden by this option.
+If no information is available, the default blocksize of tar is used.
+.TP
+.B -z
+The index file should be read and stored in compressed mode.
+.SH OPTIONS you didn't really need
+.TP
+.B --z, --no-compress
+Don't filter the archive file through gzip.
+.TP
+.B -q, --quick
+Don't extract the parent directories of the selected objects from tape.
+.BR --body
+Write only the first selected file to stdout. This is useful if you want to
+read a file or extract an archive which is part of the current archive.
+.TP
+.BR -v , --verbose
+verbose mode.
+.TP
+.B --hash-mode
+Print a hash sign for each MB.
+.TP
+.BR -V , --version
+Print only the Version Number to stderr.
+.TP
+.B -l
+Don't access the tape but print the file names to stdout.
+You may not pipe this list of pathnames into tar.
+.TP
+.B --extract
+The stdout is closed and opened by a pipe to the command
+.B "tar -fxb - 1".
+You may find this option convenient, I like to pipe the output to tar
+by hand.
+.SH EXAMPLES
+Example of
+.B getting the index
+from the default tape /dev/tape
+and storing it in file archive.idx:
+.IP
+dds2index -t archive.idx
+.PP
+Alternatively you can use a patched version of tar to create an index file.
+With the patch you can direct the errors and warning to stdout and the
+index information including information about
+the blocksize and the number of the 
+first block to a file:
+.IP
+tar -t --record-file archive.idx
+.PP
+If the archive is the first file of the tape and the blocksize is the default
+of 20, you can use the verbose output of tar (-Rv) as an index file.
+.IP
+tar -t -v -R | tee archive.idx
+.PP
+If the archive is not the first file of the tape, you can store all the
+necessary information inside the index file with the use of
+.B mt-dds
+and
+.B tar
+:
+.IP
+.Sp
+.nf
+mt asf ...
+mt-dds tell > archive.idx
+tar -tvR >>archive.idx
+.fi
+.Sp
+.PP
+Example of
+.B using dds2tar
+to extract the gnu library
+(all files containing the string "glibc" in filename)
+from the default tape /dev/tape,
+using the previously stored index file archive.idx:
+.IP
+dds2tar -t archive.idx '*glibc*' | tar xvvf -
+.PP
+.RP
+To see in advance what would happen in the previous command
+without actually writing anything to your disk,
+you may use:
+.IP
+dds2tar -t archive.idx '*glibc*' | tar tvvf -
+.PP
+Example of checking the matches. You may try:
+.IP
+dds2tar -t archive.idx -l '*glibc*'
+.PP
+\"---------------------------------------------------------------------------
+\"-----------------------
+.SH BACKGROUND INFORMATION
+.\"-----------------------
+.SS tapes
+.\"-----------
+A tape device handles all I/O (read, write, seek) in units of 
+.IR "tape records".
+The bigger a tape record, the more effective usually is
+the access (and the less gaps are on QIC-tapes).
+However, normally a program will only read or write complete tape records.
+
+Normal tape drives allow to seek only relative to the current
+position. However, some newer SCSI-2 tapes, i.e. DAT, 
+conforming to the DDS standard, 
+keep track of the absolute position on the tape by inserting the
+tape record number inside each track.
+This number can be read while
+the fast seek is performed.
+
+The
+.B tar(1) 
+program uses a slightly different terminology.
+It calls
+.IR "tape blocks"  
+what normally is called
+.IR "tape records" .
+In the following sections we use the tar terminology
+to avoid confusion.
+.SS tar
+.\"-----------
+The unit inside a 
+.B tar 
+archive is a 
+.I tar record 
+with a fixed length of 512 bytes. Every file, directory or soft link
+will occupy at least one tar record of information about
+pathname, permission information and so on called header record.
+The data of each file is stored in additional tar records directly after
+the header record of that file.
+.PP
+tar reports the 
+.I tar record number 
+of every header record in the archive with its -R option. 
+tar counts the records continuously,
+starting with 
+.B 0 
+(if invoked as tar -tR) or with 
+.B 1 
+(if invoked as tar -cR).
+.PP
+tar handles multiple records as a 
+.IR "tar block" ,
+mainly to make the access of tapes (or disks) more efficient (and save
+tape space of QIC-tapes).
+tar only writes and reads full blocks to or from an archive.
+The -b option of tar controls, how many records are in
+one block. The default number of records per block is 
+.BR 20 .
+This number is usually called the 
+.IR "tar block size" .
+However, this term is a little bit confusing, since
+it does not mean the number of bytes in a block.
+Thus a perhaps better name would be the 
+.IR "tar blocking factor" .
+
+.SS tar on tapes
+.\"-----------
+tar writes or reads its archive to or from tape in units of tar 
+blocks.
+As stated above, only a complete tape block may be transferred to/from 
+tape.  To extract a specific tar block from tape, one has to
+read an entire tape block into a buffer and extract
+the specified tar record from the buffer manually.
+If you would like to read a tar record with a given number,
+you have to know the number of the first tape block of the archive
+and the tar block size to compute the number of the tape block witch
+contains the tar record to read.
+If the tar archive is the first file on the tape, the
+.I tape block number 
+is the equal to the
+.IR "tar block number" .
+.PP
+.B Example:
+A file with the tar record number 1234 (records start with 0) 
+may be found in a tape tar archive, written with a 
+blocking factor of 20. 
+It may be found in the tar block with the number
+.RS 7
+         blk = (int) 1234/20 = (int) 61.7 = 61
+.RE
+which is also the tape block number.
+The requested file is within this tar block at the record offset 
+.RS 7
+         rec = 1234-(61*20) = 14
+.RE
+in 512 byte units.
+.PP
+If a current archive is not the first archive on the tape, then
+the number of 
+.I tape blocks 
+of all previous archives has to be
+added to the block number computed above,
+to get the
+.IR "current tape block number" .
+The number of previous tape records 
+should be obtained from DDS devices  
+when the tape is positioned 
+at the beginning of the current archive (use
+.B mt-dds
+without arguments for example).
+.PP
+.B Example:
+Assuming the archive in the above example to be the second file 
+on a tape, and the archive starts at tape block 20222. 
+Then we will find our file with tar record number 1234
+in the tape block
+.RS 7
+         tblk = 20222 + (int) 1234/20 = 20283
+.RE
+on the tape.
+The record offset inside the tape block will be the same as above.
+
+\"---------------------------------------------------------------------------
+.SH WARNING
+This program can only read records (tar is calling them tape blocks)
+up to 32 kbytes due to the limitations of the Linux device driver.
+The extracted archive is written to stdout with a
+block size of 512 bytes.
+
+.SH ENVIRONMENT
+The environment variable
+.B TAPE
+overrides the default tape device /dev/tape.
+The variable
+.B DDS2TAR cat be used to give some options, e.g.
+.B --compress, -z, -s # , -b #.
+
+.SH "SEE ALSO"
+dds2index(1), mt(1), mt-dds(1), tar(1)
+
+.SH HISTORY
+This program was created to use the fast seek operation of my DAT
+streamer. The tapes are called dds (digital data storage).
+Since the program will write a tar archive to stdout,
+I called this program
+.BR dds2tar .
+If I created the index file, I'm now
+able to restore a file of 1MB within one minute even if the tape
+contains more than 2GB of data.
+
+Thanks to Andreas (Andreas_Bagge@h2.maus.de), who has written a nice
+manual page for the overloaded version 1.1.3 of the program dds2tar
+(I added too much features ... )
+His manual page for dds2tar-1.1.3 gave me the idea how to split the
+program dds2tar into the peaces dds2tar, dds2index and mt-dds.
+Additionally his manual page was the starting point for this page.
+
+Since the version 2.2 has a very robust algorithm to read the index file
+and the ability of pattern matching, a lot of options where obsolete
+and has been deleted. I tried to make dds2tar as simple I can.
+
+.SH AUTHOR
+J"org Weule (weule@cs.uni-duesseldorf.de), Phone +49 211 751409.
+This software is available at
+ftp.uni-duesseldorf.de:/pub/unix/apollo and
+sunsite.unc.edu:/pub/Linux/system/Backup
+
diff --git a/dds2tar.ps b/dds2tar.ps
new file mode 100644 (file)
index 0000000..abfa127
--- /dev/null
@@ -0,0 +1,532 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.10
+%%CreationDate: Mon Feb  2 16:42:11 1998
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.10 0
+%%Pages: 4
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.10 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/MANUAL{
+statusdict begin/manualfeed true store end
+}bind def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 841.89 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron
+/Zcaron/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 371.08(dds2tar\(1L\) dds2tar\(1L\))72 48 R/F1 9
+/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0(dds2tar \255 tool for f)108
+96 Q(ast tape access)-.1 E F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF
+(dds2tar)108 124.8 Q F0([)2.5 E F2(-f)2.5 E/F3 10/Times-Italic@0 SF(de)
+2.5 E(vice)-.15 E F0 2.5(][)2.5 G F2(-t)A F3(inde)2.5 E(x\214le)-.2 E F0
+2.5(][)2.5 G(options])-2.5 E F3(string ...)2.5 E F1(DESCRIPTION)72 146.4
+Q F2(dds2tar)108 158.4 Q F0 .902(uses an inde)3.402 F 3.402(xt)-.15 G
+3.402<6f8c>-3.402 G .902(nd the \214les with record seek \(a f)-3.402 F
+.901(ast operation of D)-.1 F 3.121 -1.11(AT d)-.4 H -.25(ev)1.11 G
+3.401(ices\). Since).25 F .901(the \214le)3.401 F .789
+(structure of the tape archi)108 170.4 R -.15(ve)-.25 G 3.289(si).15 G
+3.289(su)-3.289 G .789(sed to e)-3.289 F .789
+(xtract the \214les, the archi)-.15 F 1.09 -.15(ve h)-.25 H .79
+(as to be created by).15 F F2(tar)3.29 E F0 3.29(,c)C(ompressed)-3.29 E
+.546(only by \(the transparent signal processor of\) the de)108 182.4 R
+3.045(vice. So)-.25 F .545(you can step through the archi)3.045 F .845
+-.15(ve ve)-.25 H .545(ry quickly).15 F .372(and e)108 194.4 R .372
+(xtract \214les.)-.15 F .372(The inde)5.372 F 2.872(xm)-.15 G .372
+(ay be created using)-2.872 F F2(dds2index)2.872 E F0(or)2.872 E F2(tar)
+2.872 E F0 .372(-vRt and is normally stored as a \214le on)B
+(your hard disk.)108 206.4 Q 2.549(At)108 223.2 S .049(ar archi)-2.549 F
+.349 -.15(ve i)-.25 H 2.549(sas).15 G .049
+(equence of blocks \(e.g. 10240 bytes by def)-2.549 F .049
+(ault\), each containing the same number \(20 by)-.1 F(def)108 235.2 Q
+.755(ault\) of records, 512 byte each.)-.1 F F2(dds2tar)5.755 E F0 .755
+(reads the tape and writes the tar records of the speci\214ed \214les)
+3.255 F 1.721(\(that means the header record and the data records of ea\
+ch selected \214le\) to stdout.)108 247.2 R -1.1(Yo)6.721 G 4.221(um)1.1
+G 1.721(ay pipe the)-4.221 F F2(dds2tar)108 259.2 Q F0 1.782
+(output to the stdin of)4.282 F F3 1.783(tar -xvvf -)4.283 F F0 1.783
+(to restore the \214les to your disk.)4.283 F(\(See)6.783 E F2(EXAMPLES)
+4.283 E F0(belo)4.283 E -.65(w.)-.25 G(\)).65 E(Before a \214le is e)108
+271.2 Q(xtracted, the records of parent directories of the \214le are a\
+lso written to stdout.)-.15 E .129(The inde)108 288 R 2.629(xo)-.15 G
+2.628(ft)-2.629 G .128(he archi)-2.628 F .428 -.15(ve s)-.25 H .128(hou\
+ld contain enough information to compute the number of the block contai\
+ning).15 F .334(the header of each selected \214le.)108 300 R F2
+(dds2index)5.335 E F0 .335(will gi)2.835 F .635 -.15(ve s)-.25 H .335
+(uch a table,).15 F F2 .335(tar -Rvt)2.835 F F0 .335
+(e.g. will not \(only record num-)2.835 F .104(bers are listed\).)108
+312 R 2.604(Ap)5.104 G .104(atch for)-2.604 F F2 .103(GNU tar)2.603 F
+(-1.12)-.37 E F0 .103(is a)2.603 F -.25(va)-.2 G .103
+(ilable, adding the option).25 F F2(--r)2.603 E(ecord-\214le.)-.18 E F0
+(Alternati)5.103 E -.15(ve)-.25 G .103(ly there).15 F
+(are some tricks to get the missing information.)108 324 Q .455
+(The strings are re)108 340.8 R .455(gular e)-.15 F .455
+(xpressions to select the \214les.)-.15 F .456
+(The matching algorithm is the one from GNU tar)5.456 F 2.956(.I)-.55 G
+(f)-2.956 E .274(the option)108 352.8 R F2(-l)2.774 E F0 .274(is gi)
+2.774 F -.15(ve)-.25 G .274
+(n, the matched \214le names are printed to stdout \(Y).15 F .273
+(ou may not pipe this list of pathnames)-1.1 F(to tar!\).)108 364.8 Q
+.726(The def)108 381.6 R .726(ault de)-.1 F .726(vice is)-.25 F F3(/de)
+3.226 E(v/rmt0)-.15 E F0 3.226(,w).47 G .726(hich may be o)-3.226 F -.15
+(ve)-.15 G .726(rridden with the en).15 F .726(vironment v)-.4 F
+(ariable)-.25 E F2 -.9(TA)3.226 G(PE).9 E F0 3.226(,w)C .726(hich in)
+-3.226 F(turn may be o)108 393.6 Q -.15(ve)-.15 G(rridden with the).15 E
+F2(-f)2.5 E F3(de)2.85 E(vice)-.15 E F0(option. The de)2.5 E
+(vice must be a SCSI tape de)-.25 E(vice.)-.25 E F1(OPTIONS)72 410.4 Q
+F2(-f)108 422.4 Q F3(de)2.85 E(vice\214le)-.15 E F0(De)2.5 E
+(vice of the tape archi)-.25 E -.15(ve)-.25 G 2.5(.M).15 G
+(ust be a SCSI tape de)-2.5 E(vice.)-.25 E F2(-t)108 439.2 Q F3(inde)
+2.51 E(x\214le)-.2 E F0(Speci\214es the inde)144 451.2 Q 2.5<788c>-.15 G
+(le \(def)-2.5 E(ault is stdin\).)-.1 E F2(-s #)108 468 Q F0 .01
+(Set the number of the \214rst tape block of the archi)21.28 F -.15(ve)
+-.25 G 2.51(.T).15 G .01(his option is useful only if the inde)-2.51 F
+2.51<788c>-.15 G .01(le con-)-2.51 F .995(tains the v)144 480 R .995
+(erbose output of)-.15 F F2 .995(tar -Rvt.)3.495 F F0(An)5.996 E 3.496
+(yi)-.15 G .996(nformation about the \214rst block inside the inde)
+-3.496 F 3.496<788c>-.15 G(le)-3.496 E .384(will be o)144 492 R -.15(ve)
+-.15 G .384(rridden by this option.).15 F .384(If no information is a)
+5.384 F -.25(va)-.2 G .384(ilable, the archi).25 F .684 -.15(ve h)-.25 H
+.384(as to be the \214rst \214le).15 F(of the tape. If you ha)144 504 Q
+.3 -.15(ve p)-.2 H
+(ositioned your tape at the \214rst block of the archi).15 E -.15(ve)
+-.25 G 2.5(,y).15 G(ou can use)-2.5 E F2
+(dds2tar `mt-dds` -t index ... | tar -f - ...)144 520.8 Q F0
+(to complete the information of the output of)144 537.6 Q F2(tar -Rvt)
+2.5 E F0(stored in the inde)2.5 E 2.5<788c>-.15 G(le.)-2.5 E F2(-b #)108
+554.4 Q F0 .639(Set the blocksize of the archi)19.61 F .939 -.15(ve \()
+-.25 H .64(tar -b #\). This option is useful only if the inde).15 F 3.14
+<788c>-.15 G .64(le contains the)-3.14 F -.15(ve)144 566.4 S .183
+(rbose output of tar \(or if you ha).15 F .483 -.15(ve p)-.2 H .183
+(roblems with the size of the internal b).15 F(uf)-.2 E .182
+(fer of dds2tar\).)-.25 F(An)5.182 E(y)-.15 E .209
+(information about the blocksize inside the inde)144 578.4 R 2.709<788c>
+-.15 G .209(le will be o)-2.709 F -.15(ve)-.15 G .21
+(rridden by this option.).15 F .21(If no infor)5.21 F(-)-.2 E
+(mation is a)144 590.4 Q -.25(va)-.2 G(ilable, the def).25 E
+(ault blocksize of tar is used.)-.1 E F2(-z)108 607.2 Q F0(The inde)
+28.23 E 2.5<788c>-.15 G
+(le should be read and stored in compressed mode.)-2.5 E F1(OPTIONS y)72
+624 Q(ou didn't r)-.225 E(eally need)-.162 E F2(--z, --no-compr)108 636
+Q(ess)-.18 E F0(Don')144 648 Q 2.5<748c>-.18 G(lter the archi)-2.5 E .3
+-.15(ve \214)-.25 H(le through gzip.).15 E F2(-q, --quick)108 664.8 Q F0
+(Don')144 676.8 Q 3.205(te)-.18 G .705
+(xtract the parent directories of the selected objects from tape.)-3.355
+F F2(--body)5.704 E F0 .704(Write only the \214rst)3.204 F .161
+(selected \214le to stdout. This is useful if you w)144 688.8 R .161
+(ant to read a \214le or e)-.1 F .161(xtract an archi)-.15 F .461 -.15
+(ve w)-.25 H .161(hich is part of).15 F(the current archi)144 700.8 Q
+-.15(ve)-.25 G(.).15 E 220.25(2.3 1)299.75 768 R EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 371.08(dds2tar\(1L\) dds2tar\(1L\))72 48 R/F1 10
+/Times-Bold@0 SF(-v)108 84 Q F0(,)A F1(--v)A(erbose)-.1 E F0 -.15(ve)144
+96 S(rbose mode.).15 E F1(--hash-mode)108 112.8 Q F0
+(Print a hash sign for each MB.)144 124.8 Q F1(-V)108 141.6 Q F0(,)A F1
+(--v)A(ersion)-.1 E F0(Print only the V)144 153.6 Q
+(ersion Number to stderr)-1.11 E(.)-.55 E F1(-l)108 170.4 Q F0(Don')
+29.89 E 3.226(ta)-.18 G .726(ccess the tape b)-3.226 F .726
+(ut print the \214le names to stdout.)-.2 F -1.1(Yo)5.725 G 3.225(um)1.1
+G .725(ay not pipe this list of pathnames)-3.225 F(into tar)144 182.4 Q
+(.)-.55 E F1(--extract)108 199.2 Q F0 .22
+(The stdout is closed and opened by a pipe to the command)144 211.2 R F1
+.221(tar -fxb - 1 .)2.721 F F0 -1.1(Yo)5.221 G 2.721(um)1.1 G .221
+(ay \214nd this option)-2.721 F(con)144 223.2 Q -.15(ve)-.4 G
+(nient, I lik).15 E 2.5(et)-.1 G 2.5(op)-2.5 G
+(ipe the output to tar by hand.)-2.5 E/F2 9/Times-Bold@0 SF(EXAMPLES)72
+240 Q F0(Example of)108 252 Q F1(getting the index)2.5 E F0
+(from the def)2.5 E(ault tape /de)-.1 E
+(v/rmt0 and storing it in \214le archi)-.25 E -.15(ve)-.25 G(.idx:).15 E
+(dds2inde)144 268.8 Q 2.5(x-)-.15 G 2.5(ta)-2.5 G(rchi)-2.5 E -.15(ve)
+-.25 G(.idx).15 E(Alternati)108 285.6 Q -.15(ve)-.25 G .271
+(ly you can use a patched v).15 F .271(ersion of tar to create an inde)
+-.15 F 2.771<788c>-.15 G 2.771(le. W)-2.771 F .271
+(ith the patch you can direct the)-.4 F .801(errors and w)108 297.6 R
+.801(arning to stdout and the inde)-.1 F 3.301(xi)-.15 G .802
+(nformation including information about the blocksize and the)-3.301 F
+(number of the \214rst block to a \214le:)108 309.6 Q
+(tar -t --record-\214le archi)144 326.4 Q -.15(ve)-.25 G(.idx).15 E .385
+(If the archi)108 343.2 R .685 -.15(ve i)-.25 H 2.885(st).15 G .384
+(he \214rst \214le of the tape and the blocksize is the def)-2.885 F
+.384(ault of 20, you can use the v)-.1 F .384(erbose out-)-.15 F
+(put of tar \(-Rv\) as an inde)108 355.2 Q 2.5<788c>-.15 G(le.)-2.5 E
+(tar -t -v -R | tee archi)144 372 Q -.15(ve)-.25 G(.idx).15 E .203
+(If the archi)108 388.8 R .503 -.15(ve i)-.25 H 2.703(sn).15 G .204(ot \
+the \214rst \214le of the tape, you can store all the necessary informa\
+tion inside the inde)-2.703 F 2.704<788c>-.15 G(le)-2.704 E
+(with the use of)108 400.8 Q F1(mt-dds)2.5 E F0(and)2.5 E F1(tar)2.5 E
+F0(:)2.5 E(mt asf ...)144 417.6 Q(mt-dds tell > archi)144 429.6 Q -.15
+(ve)-.25 G(.idx).15 E(tar -tvR >>archi)144 441.6 Q -.15(ve)-.25 G(.idx)
+.15 E .057(Example of)108 458.4 R F1 .057(using dds2tar)2.557 F F0 .057
+(to e)2.557 F .056(xtract the gnu library \(all \214les containing the \
+string "glibc" in \214lename\) from)-.15 F(the def)108 470.4 Q
+(ault tape /de)-.1 E(v/rmt0, using the pre)-.25 E(viously stored inde)
+-.25 E 2.5<788c>-.15 G(le archi)-2.5 E -.15(ve)-.25 G(.idx:).15 E
+(dds2tar -t archi)144 487.2 Q -.15(ve)-.25 G
+(.idx '*glibc*' | tar xvvf -).15 E 2.206 -.8(To s)108 504 T .606
+(ee in adv).8 F .607(ance what w)-.25 F .607(ould happen in the pre)-.1
+F .607(vious command without actually writing an)-.25 F .607
+(ything to your)-.15 F(disk, you may use:)108 516 Q(dds2tar -t archi)144
+532.8 Q -.15(ve)-.25 G(.idx '*glibc*' | tar tvvf -).15 E
+(Example of checking the matches. Y)108 549.6 Q(ou may try:)-1.1 E
+(dds2tar -t archi)144 566.4 Q -.15(ve)-.25 G(.idx -l '*glibc*').15 E F2
+-.27(BA)72 612 S(CKGR)-.225 E(OUND INFORMA)-.27 E(TION)-.855 E F1(tapes)
+87 624 Q F0 2.517(At)108 636 S .017(ape de)-2.517 F .017
+(vice handles all I/O \(read, write, seek\) in units of)-.25 F/F3 10
+/Times-Italic@0 SF .016(tape r)2.516 F(ecor)-.37 E(ds)-.37 E F0 5.016
+(.T).27 G .016(he bigger a tape record, the more)-5.016 F(ef)108 648 Q
+(fecti)-.25 E .362 -.15(ve u)-.25 H .063
+(sually is the access \(and the less g).15 F .063
+(aps are on QIC-tapes\).)-.05 F(Ho)5.063 E(we)-.25 E -.15(ve)-.25 G .863
+-.4(r, n).15 H .063(ormally a program will only).4 F
+(read or write complete tape records.)108 660 Q .433(Normal tape dri)108
+684 R -.15(ve)-.25 G 2.933(sa).15 G(llo)-2.933 E 2.933(wt)-.25 G 2.933
+(os)-2.933 G .433(eek only relati)-2.933 F .733 -.15(ve t)-.25 H 2.932
+(ot).15 G .432(he current position. Ho)-2.932 F(we)-.25 E -.15(ve)-.25 G
+1.232 -.4(r, s).15 H .432(ome ne).4 F .432(wer SCSI-2 tapes,)-.25 F .553
+(i.e. D)108 696 R -1.02 -1.11(AT ,)-.4 H .553
+(conforming to the DDS standard, k)4.163 F .554
+(eep track of the absolute position on the tape by inserting the)-.1 F
+(tape record number inside each track.)108 708 Q
+(This number can be read while the f)5 E(ast seek is performed.)-.1 E
+220.25(2.3 2)299.75 768 R EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 371.08(dds2tar\(1L\) dds2tar\(1L\))72 48 R(The)
+108 84 Q/F1 10/Times-Bold@0 SF(tar\(1\))3.045 E F0 .545
+(program uses a slightly dif)3.045 F .545(ferent terminology)-.25 F
+5.545(.I)-.65 G 3.045(tc)-5.545 G(alls)-3.045 E/F2 10/Times-Italic@0 SF
+.545(tape bloc)3.045 F(ks)-.2 E F0 .545(what normally is called)3.045 F
+F2(tape)3.045 E -.37(re)108 96 S(cor).37 E(ds)-.37 E F0 5(.I).27 G 2.5
+(nt)-5 G(he follo)-2.5 E(wing sections we use the tar terminology to a)
+-.25 E -.2(vo)-.2 G(id confusion.).2 E F1(tar)87 112.8 Q F0 .814
+(The unit inside a)108 124.8 R F1(tar)3.314 E F0(archi)3.314 E 1.115
+-.15(ve i)-.25 H 3.315(sa).15 G F2 .815(tar r)B(ecor)-.37 E(d)-.37 E F0
+.815(with a \214x)3.315 F .815(ed length of 512 bytes. Ev)-.15 F .815
+(ery \214le, directory or soft)-.15 F .777(link will occup)108 136.8 R
+3.277(ya)-.1 G 3.277(tl)-3.277 G .777(east one tar record of informatio\
+n about pathname, permission information and so on)-3.277 F .118
+(called header record.)108 148.8 R .119(The data of each \214le is stor\
+ed in additional tar records directly after the header record)5.119 F
+(of that \214le.)108 160.8 Q .937(tar reports the)108 177.6 R F2 .937
+(tar r)3.437 F(ecor)-.37 E 3.437(dn)-.37 G(umber)-3.437 E F0 .936(of e)
+3.437 F -.15(ve)-.25 G .936(ry header record in the archi).15 F 1.236
+-.15(ve w)-.25 H .936(ith its -R option.).15 F .936(tar counts the)5.936
+F(records continuously)108 189.6 Q 2.5(,s)-.65 G(tarting with)-2.5 E F1
+(0)2.5 E F0(\(if in)2.5 E -.2(vo)-.4 G -.1(ke).2 G 2.5(da).1 G 2.5(st)
+-2.5 G(ar -tR\) or with)-2.5 E F1(1)2.5 E F0(\(if in)2.5 E -.2(vo)-.4 G
+-.1(ke).2 G 2.5(da).1 G 2.5(st)-2.5 G(ar -cR\).)-2.5 E .074
+(tar handles multiple records as a)108 206.4 R F2 .074(tar bloc)2.574 F
+(k)-.2 E F0 2.574(,m).67 G .074(ainly to mak)-2.574 F 2.574(et)-.1 G
+.074(he access of tapes \(or disks\) more ef)-2.574 F .075
+(\214cient \(and)-.25 F(sa)108 218.4 Q .443 -.15(ve t)-.2 H .143
+(ape space of QIC-tapes\).).15 F .142
+(tar only writes and reads full blocks to or from an archi)5.143 F -.15
+(ve)-.25 G 5.142(.T).15 G .142(he -b option of)-5.142 F .238
+(tar controls, ho)108 230.4 R 2.738(wm)-.25 G(an)-2.738 E 2.738(yr)-.15
+G .238(ecords are in one block. The def)-2.738 F .239
+(ault number of records per block is)-.1 F F1(20)2.739 E F0 5.239(.T)C
+.239(his num-)-5.239 F .628(ber is usually called the)108 242.4 R F2
+.628(tar bloc)3.128 F 3.128(ks)-.2 G(ize)-3.128 E F0 5.628(.H).18 G -.25
+(ow)-5.628 G -2.15 -.25(ev e).25 H 1.428 -.4(r, t).25 H .627
+(his term is a little bit confusing, since it does not mean).4 F
+(the number of bytes in a block.)108 254.4 Q
+(Thus a perhaps better name w)5 E(ould be the)-.1 E F2(tar bloc)2.5 E
+(king factor)-.2 E F0(.).73 E F1(tar on tapes)87 283.2 Q F0 .529
+(tar writes or reads its archi)108 295.2 R .829 -.15(ve t)-.25 H 3.029
+(oo).15 G 3.029(rf)-3.029 G .529(rom tape in units of tar blocks.)-3.029
+F .529(As stated abo)5.529 F -.15(ve)-.15 G 3.029(,o).15 G .529
+(nly a complete tape)-3.029 F .629
+(block may be transferred to/from tape.)108 307.2 R 2.229 -.8(To e)5.629
+H .629
+(xtract a speci\214c tar block from tape, one has to read an entire).65
+F .517(tape block into a b)108 319.2 R(uf)-.2 E .517(fer and e)-.25 F
+.517(xtract the speci\214ed tar record from the b)-.15 F(uf)-.2 E .518
+(fer manually)-.25 F 5.518(.I)-.65 G 3.018(fy)-5.518 G .518(ou w)-3.018
+F .518(ould lik)-.1 F 3.018(et)-.1 G(o)-3.018 E .688
+(read a tar record with a gi)108 331.2 R -.15(ve)-.25 G 3.188(nn).15 G
+(umber)-3.188 E 3.188(,y)-.4 G .688(ou ha)-3.188 F .988 -.15(ve t)-.2 H
+3.188(ok).15 G(no)-3.188 E 3.188(wt)-.25 G .688
+(he number of the \214rst tape block of the archi)-3.188 F -.15(ve)-.25
+G .351(and the tar block size to compute the number of the tape block w\
+itch contains the tar record to read.)108 343.2 R .351(If the)5.351 F
+(tar archi)108 355.2 Q .3 -.15(ve i)-.25 H 2.5(st).15 G
+(he \214rst \214le on the tape, the)-2.5 E F2(tape bloc)2.5 E 2.5(kn)-.2
+G(umber)-2.5 E F0(is the equal to the)2.5 E F2(tar bloc)2.5 E 2.5(kn)-.2
+G(umber)-2.5 E F0(.).73 E F1(Example:)108 372 Q F0 2.861<418c>2.861 G
+.36(le with the tar record number 1234 \(records start with 0\) may be \
+found in a tape tar archi)-2.861 F -.15(ve)-.25 G(,).15 E
+(written with a blocking f)108 384 Q(actor of 20.)-.1 E
+(It may be found in the tar block with the number)5 E
+(blk = \(int\) 1234/20 = \(int\) 61.7 = 61)165.5 396 Q
+(which is also the tape block number)108 408 Q 5(.T)-.55 G
+(he requested \214le is within this tar block at the record of)-5 E
+(fset)-.25 E(rec = 1234-\(61*20\) = 14)165.5 420 Q(in 512 byte units.)
+108 432 Q 1.625(If a current archi)108 448.8 R 1.925 -.15(ve i)-.25 H
+4.125(sn).15 G 1.625(ot the \214rst archi)-4.125 F 1.925 -.15(ve o)-.25
+H 4.125(nt).15 G 1.625(he tape, then the number of)-4.125 F F2 1.625
+(tape bloc)4.125 F(ks)-.2 E F0 1.625(of all pre)4.125 F(vious)-.25 E
+(archi)108 460.8 Q -.15(ve)-.25 G 3.032(sh).15 G .531
+(as to be added to the block number computed abo)-3.032 F -.15(ve)-.15 G
+3.031(,t).15 G 3.031(og)-3.031 G .531(et the)-3.031 F F2(curr)3.031 E
+.531(ent tape bloc)-.37 F 3.031(kn)-.2 G(umber)-3.031 E F0 5.531(.T).73
+G(he)-5.531 E .722(number of pre)108 472.8 R .723
+(vious tape records should be obtained from DDS de)-.25 F .723
+(vices when the tape is positioned at the)-.25 F(be)108 484.8 Q
+(ginning of the current archi)-.15 E .3 -.15(ve \()-.25 H(use).15 E F1
+(mt-dds)2.5 E F0(without ar)2.5 E(guments for e)-.18 E(xample\).)-.15 E
+F1(Example:)108 501.6 Q F0 .205(Assuming the archi)2.705 F .505 -.15
+(ve i)-.25 H 2.704(nt).15 G .204(he abo)-2.704 F .504 -.15(ve ex)-.15 H
+.204(ample to be the second \214le on a tape, and the archi).15 F .504
+-.15(ve s)-.25 H(tarts).15 E(at tape block 20222.)108 513.6 Q(Then we w\
+ill \214nd our \214le with tar record number 1234 in the tape block)5 E
+(tblk = 20222 + \(int\) 1234/20 = 20283)165.5 525.6 Q(on the tape.)108
+537.6 Q(The record of)5 E
+(fset inside the tape block will be the same as abo)-.25 E -.15(ve)-.15
+G(.).15 E/F3 9/Times-Bold@0 SF -1.08(WA)72 578.4 S(RNING)1.08 E F0 .503
+(This program can only read records \(tar is calling them tape blocks\)\
+ up to 32 kbytes due to the limitations)108 590.4 R(of the Linux de)108
+602.4 Q(vice dri)-.25 E -.15(ve)-.25 G 3.6 -.55(r. T).15 H(he e).55 E
+(xtracted archi)-.15 E .3 -.15(ve i)-.25 H 2.5(sw).15 G
+(ritten to stdout with a block size of 512 bytes.)-2.5 E F3(ENVIR)72
+631.2 Q(ONMENT)-.27 E F0 .587(The en)108 643.2 R .587(vironment v)-.4 F
+(ariable)-.25 E F1 -.9(TA)3.087 G(PE).9 E F0 -.15(ove)3.087 G .587
+(rrides the def).15 F .587(ault tape de)-.1 F .587(vice /de)-.25 F 3.087
+(v/rmt0. The)-.25 F -.25(va)3.087 G(riable).25 E F1(DDS2T)3.087 E .586
+(AR cat)-.9 F(be used to gi)108 655.2 Q .2 -.1(ve s)-.1 H
+(ome options, e.g).1 E 5(.-)-.15 G(-compr)-5 E(ess, -z, -s # , -b #.)
+-.18 E F3(SEE ALSO)72 684 Q F0(dds2inde)108 696 Q
+(x\(1\), mt\(1\), mt-dds\(1\), tar\(1\))-.15 E 220.25(2.3 3)299.75 768 R
+EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 371.08(dds2tar\(1L\) dds2tar\(1L\))72 48 R/F1 9
+/Times-Bold@0 SF(HIST)72 84 Q(OR)-.162 E(Y)-.315 E F0 .025
+(This program w)108 96 R .025(as created to use the f)-.1 F .025
+(ast seek operation of my D)-.1 F 2.245 -1.11(AT s)-.4 H(treamer)1.11 E
+2.525(.T)-.55 G .026(he tapes are called dds \(digi-)-2.525 F .745
+(tal data storage\).)108 108 R .744
+(Since the program will write a tar archi)5.745 F 1.044 -.15(ve t)-.25 H
+3.244(os).15 G .744(tdout, I called this program)-3.244 F/F2 10
+/Times-Bold@0 SF(dds2tar)3.244 E F0 5.744(.I)C 3.244(fI)-5.744 G .99
+(created the inde)108 120 R 3.49<788c>-.15 G .99(le, I'm no)-3.49 F 3.49
+(wa)-.25 G .991(ble to restore a \214le of 1MB within one minute e)-3.49
+F -.15(ve)-.25 G 3.491(ni).15 G 3.491(ft)-3.491 G .991(he tape contains)
+-3.491 F(more than 2GB of data.)108 132 Q .374(Thanks to Andreas \(Andr\
+eas_Bagge@h2.maus.de\), who has written a nice manual page for the o)108
+156 R -.15(ve)-.15 G(rloaded).15 E -.15(ve)108 168 S .05(rsion 1.1.3 of\
+ the program dds2tar \(I added too much features ... \) His manual page\
+ for dds2tar).15 F .05(-1.1.3 g)-.2 F -2.25 -.2(av e)-.05 H .542
+(me the idea ho)108 180 R 3.042(wt)-.25 G 3.042(os)-3.042 G .542
+(plit the program dds2tar into the peaces dds2tar)-3.042 F 3.042(,d)-.4
+G(ds2inde)-3.042 E 3.042(xa)-.15 G .541(nd mt-dds.)-3.042 F
+(Additionally)5.541 E(his manual page w)108 192 Q
+(as the starting point for this page.)-.1 E .107(Since the v)108 216 R
+.107(ersion 2.2 has a v)-.15 F .107(ery rob)-.15 F .107
+(ust algorithm to read the inde)-.2 F 2.608<788c>-.15 G .108
+(le and the ability of pattern matching, a)-2.608 F
+(lot of options where obsolete and has been deleted. I tried to mak)108
+228 Q 2.5(ed)-.1 G(ds2tar as simple I can.)-2.5 E F1 -.45(AU)72 256.8 S
+(THOR).45 E F0(J"or)108 268.8 Q 3.029(gW)-.18 G .529
+(eule \(weule@cs.uni-duesseldorf.de\), Phone +49 211 751409.)-3.829 F
+.528(This softw)5.528 F .528(are is a)-.1 F -.25(va)-.2 G .528
+(ilable at ftp.uni-).25 F(duesseldorf.de:/pub/unix/apollo and sunsite.u\
+nc.edu:/pub/Linux/system/Backup)108 280.8 Q 220.25(2.3 4)299.75 768 R EP
+%%Trailer
+end
+%%EOF
diff --git a/dds_chkhdr.c b/dds_chkhdr.c
new file mode 100644 (file)
index 0000000..39a6ba3
--- /dev/null
@@ -0,0 +1,39 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mtio.h>
+#include <unistd.h>
+#include <string.h>
+#include "dds2tar.h"
+#include "dds_tape.h"
+
+int dds_is_tar_header_record(tar_record*const ptr){
+       int     i;
+       unsigned int     n = 0;
+       unsigned char   *p = (char*)ptr ;
+
+       for (i = 0; i < 148; i++)
+               n += p[i];
+       for (i = 0; i < 8; i++)
+               n += ' ';
+       for (i = 156; i < 512; i++)
+               n += p[i];
+       sscanf(p + 148, "%8o", &i);
+       if ( n != ((int)' ') * 8 ){
+               if ( i == 0 ) {
+                       sprintf(p+148 , "%o", n );
+               } else
+               if ( i != n ) return 0;
+               sscanf(ptr->hdr.size,"%o",&i);
+               i += 512 + 511 ;
+               i >>= 9 ;
+       } else i=1 ;
+       return i;
+}
+
+
diff --git a/dds_extract.c b/dds_extract.c
new file mode 100644 (file)
index 0000000..45e7daf
--- /dev/null
@@ -0,0 +1,598 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mtio.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * fnmatch() and FNM_LEADING_DIR
+ */
+#define _GNU_SOURCE 1
+#include <fnmatch.h>
+
+#include "dds2tar.h"
+#include "dds_tape.h"
+
+/*
+ * Compare two strings
+ *
+ */
+int dds_strcmp(const char*n1,const char*n2){
+       int i = 0 ;
+       int j = 0 ;
+       while ( 1 ){
+               while ( n1[i] == '\\' ) i++ ;
+               while ( n2[j] == '\\' ) j++ ;
+               if ( i > 90 || j > 90 || n1[i] == '\0' || n2[j] == '\0' )
+                       return 0 ;
+               if  ( n1[i] != n2[j] ) return 1 ;
+               i++ ;
+               j++ ;
+       }
+       return 0 ;
+}
+
+/*
+ * To count the number of blocks written, we use the variable nblocks.
+ */
+static int nblocks = 0;
+
+/*
+ * Fill the buffer 'cur_block' the block of the given number.
+ * first we check the block number of the copy that is hold inside the
+ * buffer cur_block.
+ */
+static int
+set_cur_block(int const sb)
+{
+       int     n;
+
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+       fprintf(stderr, "set_cur_block(%d)\n", sb);
+#endif
+
+       if (sb != cur_blkno) {
+               /*
+                * We have to read the block.
+                */
+               next_blkno = dds_getpos(device);
+               /*
+                * next_blkno stores now the number of the next block of the
+                * tape.
+                */
+               n = sb - next_blkno;
+               /*
+                * In some cases reading is faster then seeking.
+                */
+               if ((n > 0) && (n < DONT_SKIP)) {
+                       do {
+                               dds_read_block();
+                       } while ((--n) > 0);
+               }
+               /*
+                * Now we should be at the position.
+                */
+               n = sb - next_blkno;
+               if (n != 0) {
+                       dds_seek(device, sb);
+                       next_blkno = sb;
+               }
+               /*
+                * Now we read the block. cur_n == 0 indicates a filemark.
+                */
+               dds_read_block();
+       }
+       return 0;
+}
+
+/*
+ * procedure to extract the files from the specified area (sb:sr-eb:er).
+ * If area is of the form (sb:sr-0:0), the file at position (sb,sr) is
+ * extracted. The length of the file is read from the tar header record.
+ *
+ * If list_only is set to 1, only the name of the extraction is printed.
+ */
+static int
+extract(char const *const name, int const sb, int const sr)
+{
+
+       int     cur_rec, n, size;
+       char   *p;
+
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+       fprintf(stderr, "extract(%s,%d,%d)\n", name, sb, sr);
+#endif
+
+       /*
+        * Print only the name.
+        */
+       if (list_only == 1) {
+               printf("%7d%3d: %s\n", sb, sr, name);
+               return 0;
+       }
+       /*
+        * Print the filename and the location for verbose output.
+        */
+       if (verbose != 0) {
+               fprintf(stderr,
+                       "dds2tar at rec %d: %7d%3d: %s\n",
+                       nblocks, sb, sr, name);
+       }
+       /*
+        * Check the buffer for the right tape block.
+        */
+       set_cur_block(sb);
+
+       cur_rec = sr;
+       /*
+        * Check the header block.
+        * The Name field should contain the given name.
+        * The Program will stop if its not.
+        *
+        * Note that for links we can only compare the first
+        * characters, when the index contains somethins like
+        * 'linkname -> filename' (soft link) or
+        * 'linkname link to filename' (hard link)
+        * doesn't match 'linkname'.
+        */
+       p = (char*) (cur_block + cur_rec) ;
+       if ( dds_is_tar_header_record((tar_record*)p) == 0 ) {
+               fprintf(stderr,
+                       " dds2tar: FATAL ERROR\n"
+                       " dds2tar: header expected, not found\n"
+               );
+               if ( force_nochk == 0 ) exit(5);
+       }
+       if (name != NULL)
+       if ( ( (dds_strcmp(name, p)!=0 )
+               && (((tar_record*)p)->hdr.linkflag!='2')
+               && (((tar_record*)p)->hdr.linkflag!='1')
+               ) || ( strstr(name, p)!=name ) ) {
+               fprintf(stderr,
+                       "dds2tar: FATAL ERROR\n"
+                       "dds2tar: Looked for %s at %d %d\n"
+                       "dds2tar: Could not find %s at %d %d.\n"
+                       "dds2tar: Found %s\n"
+                       "dds2tar: Link flag: %c\n"
+                       "dds2tar: Is it the right tape?\n",
+                       name, sb , sr ,
+                       name, dds_getpos(device) - 1, cur_rec,p,
+                       ((tar_record*)p)->hdr.linkflag);
+               if ( force_nochk == 0 ) exit(5);
+       }
+       /*
+        * First calculate the number of records of the object.
+        */
+       size = 0;
+       n = 1;
+
+       p = cur_block[cur_rec].hdr.size;
+       if (*p != '\0') {
+               sscanf(p, "%o", &size);
+               n = size;
+               n += 1023;
+               n >>= 9;
+       }
+       /*
+        * Now write the records to stdout.
+        */
+       if (verbose) {
+               fprintf(stderr,
+                       "dd2tar: %s needs %d blocks\n", name, n);
+       }
+       if ( write_body == 1 ) {
+               cur_rec++;
+               while ((size > 0) && (cur_n > 0)) {
+                       if (cur_rec >= cur_bs) {
+                               dds_read_block();
+                               cur_rec = 0;
+                       }
+                       write(1, cur_block + cur_rec, (size>=512)? 512:size );
+                       size -= 512 ;
+                       cur_rec++;
+               }
+               exit(0);
+       }
+       while ((n > 0) && (cur_n > 0)) {
+               if (cur_rec >= cur_bs) {
+                       dds_read_block();
+                       cur_rec = 0;
+               }
+               write(1, cur_block + cur_rec, 512);
+               nblocks++;
+               n--;
+               cur_rec++;
+       }
+       return 0;
+}
+
+#ifdef EXP_STUFF
+int
+extract_loc(char const *const *loc_list)
+{
+       int cur_rec ;
+
+       while (*loc_list != NULL) {
+               int     eb, er, sb, sr;
+
+               sscanf(*loc_list, "%u:%u-%u:%u", &sb, &sr, &eb, &er);
+               set_cur_block(sb);
+               cur_rec = sr ;
+               while (cur_n > 0) {
+                       int     i;
+
+                       if ((cur_n & 0x1ff) != 0) {
+                               fprintf(stderr,
+                                       "tape record size (%d) is not a"
+                                       " multiple of tar records\n"
+                                       , cur_n
+                                       );
+                               close(device);
+                               exit(6);
+                       }
+                       i = cur_n >> 9;
+                       if (cur_blkno == eb)
+                               i = er;
+                       while (cur_rec < i) {
+                               write(1, cur_block + cur_rec++, 512);
+                               nblocks++;
+                       }
+                       /*
+                        * if eb==-1 extract until eof
+                        */
+                       if ((cur_rec == er && cur_blkno == eb))
+                               break;
+                       i = cur_blkno + 1;
+                       cur_rec = 0;
+                       if ((cur_rec == er && cur_blkno == eb))
+                               break;
+                       dds_read_block();
+               }
+               loc_list++;
+       }
+       return 0;
+}
+
+#endif
+
+/*
+ * Now we are scanning the table of contents (index file) and match the
+ * pathnames there with the given pattern. If a pattern matches, we
+ * extract the parent directories (dir_extract()) and the file.
+ */
+int
+dds_cmp(char const *const *const pattern_list)
+{
+       int i ;
+       char *fgets_return_value ;
+       char const *const *p;
+       int so = 0 ; /*scanoffset*/
+
+       /*
+        * To scan the line of the table of contents (index file)
+        * we need some variables.
+        */
+       char   *name = NULL;
+       int     blkno, recno, size;
+
+       /*
+        * List of directories entries.
+        */
+       struct dir_list {
+               char    n[128-2*sizeof(int)];   /* name of the dir */
+               int     b, r;   /* block address */
+       }
+              *dl;
+       int     de = 0;         /* first empty list entry */
+
+       /*
+        * Format of the table of contents.
+        *      dds2index --> tar_index_file == 0
+        *      tar -Rvt  --> tar_index_file == 1
+        */
+       int     tar_index_file = 1;
+
+       /*
+        * Bug fix for tar. First record number found inside the
+        * table of contents (index file).
+        */
+       int     tar_first_recno = -1;
+
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+       fprintf(stderr,"dds_cmp(%s ...)\n",*pattern_list);
+#endif
+
+
+       /*
+        * First we need some memory.
+        */
+       dl = malloc(sizeof (*dl) * 64);
+       if (dl == NULL) {
+               close(device);
+               fprintf(stderr, "dds2tar: no address space available\n");
+               exit(7);
+       }
+       memset(cur_line, 0, 1024);
+
+       /*
+        * Scan the table of conten|s (index file) until eof.
+        */
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+#endif
+       while (!feof(index_fp)) {
+               fgets_return_value = fgets(cur_line, MAXPATHLEN<<2, index_fp);
+               if ( fgets_return_value == NULL ) {
+                       if ( feof(index_fp) ) {
+                               break ;
+                       } else {
+                               perror("dds2tar");
+                               exit(1);
+                       }
+               }
+#ifdef DDS_TRACE
+               fprintf(stderr,"%d\n",__LINE__);
+               fputs(cur_line, stderr);
+#endif
+
+               /*
+                * Check for comment and empty lines.
+                */
+               if ((*cur_line == '#') ||
+                   (*cur_line == ' ') ||
+                   (*cur_line == '\0'))
+                       continue;
+
+               /*
+                * Check the line for location information.
+                */
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+#endif
+               if (0 == rt_loc_line())
+                       continue;
+
+               /*
+                * Check for the first line of the dds2index.
+                */
+               if ((0 == strcmp(cur_line, dds_headline)) 
+               || (0 == strcmp(cur_line, dds_old_headline))) {
+                       tar_index_file = 0;
+                       tar_n = buf_n ;
+                       tar_bs = buf_n >> 9 ;
+                       if ( vid != HP ) dds_set_bs(tar_n);
+                       continue;
+               }
+#ifdef DDS_TRACE
+               fprintf(stderr,"%d\n",__LINE__);
+#endif
+
+               /*
+                * dds2index indicates eof with the string '-end-'.
+                * This line has to be processed in the normal way.
+                * We can stop now processing.
+                */
+               if ((*cur_line == '-') &&
+                   (strncmp(cur_line, "-end-", 5) == 0)) {
+#ifdef DDS_TRACE
+                       fprintf(stderr,"%d\n",__LINE__);
+#endif
+                       break;
+               }
+
+               /*
+                * Scan the line of the index.
+                * Note: The index file of dds2index contains the magic string
+                *   of the tar header, witch depends on the used tar version.
+                */
+               if (tar_index_file == 0) {
+                       rt_line(&blkno, &recno, &size, &name);
+               } else {
+                       /*
+                        * check for record line
+                        */
+                       if ((0 != strncmp(cur_line, "rec", 3)) &&
+                          (0 != strncmp(cur_line, "block", 5)))
+                               continue;
+
+                       /*
+                        * cook the input line and delete all the quoted
+                        * characters.
+                        */
+                       dds_unquote(cur_line);
+
+                       /*
+                        * Set scanoffset
+                        */
+                       so = (0 == strncmp(cur_line, "block", 5))? 2 : 0 ;
+                       
+                       recno = atoi(cur_line + 4 + so );
+                       /*
+                        * tar-1.13 writes now the block number:
+                        */
+                       if ( so == 0 ){
+                               int x ;
+                               int n ;
+                               char c;
+                               if ( 2 == sscanf(
+                                       cur_line+16,"block %d%c%n",&x,&c,&n
+                                       ) && c == ':' ) {
+                                       so += n + 1 ;
+                                       recno = x ;
+#ifdef DDS_TRACE
+                                       fprintf(stderr,"Blocks found:%d\n",x);
+#endif
+                               }
+                       }
+                       /*
+                        * Now we are fixing a bug of gnu tar ...
+                        * The first number should be zero, othewise we
+                        * correct all the numbers.
+                        * If tar_first_recno is .lt. zero, no recno is read
+                        * up to now.
+                        */
+                       if (tar_first_recno < 0)
+                               tar_first_recno = recno;
+                       recno -= tar_first_recno;
+                       /*
+                        * Calculate the block number of the record.
+                        */
+#ifdef DDS_TRACE
+                       fprintf(stderr,"file-loc(%d,%d)\n",recno,tar_fb);
+#endif
+                       blkno = recno / tar_bs;
+                       recno -= blkno * tar_bs;
+                       if ( vid != HP ) blkno *= tar_bs ;
+#ifdef DDS_TRACE
+                       fprintf(stderr,"file-loc(%d:%d,%d)\n",tar_bs,blkno,recno);
+#endif
+                       blkno += tar_fb;
+#ifdef DDS_TRACE
+                       fprintf(stderr,"file-loc(%d:%d,%d)\n",tar_bs,blkno,recno);
+#endif
+                       if (name == NULL) {     /* calculate only once */
+                               if ( strlen(cur_line) >= (66) ) {
+                                       name = cur_line + (65);
+                                       while ( ( name[ 0] != '\0' )
+                                        && ((     ( name[-1] != ' '  )
+                                               || ( name[-6] != ' '  )
+                                               || ( name[-9] != ':'  )
+                                        )&&(      ( name[-1] != ' '  )
+                                               || ( name[-4] != ':'  )
+                                               || ( name[-7] != ' '  )
+                                               || ( name[-10] != '-'  )
+                                               || ( name[-13] != '-'  )
+                                        ))
+                                       ) name++ ;
+                                       if ( name[0] == '\0' ) {
+                                               name = cur_line + (16+so);
+                                       }
+                               } else {
+                                       if ( strlen(cur_line) <= (16+so) ) {
+                                               strcat(cur_line,
+                                               "                    ");
+                                       }
+                                       name = cur_line + (16+so);
+                               }
+#ifdef DDS_TRACE
+                               fprintf(stderr,"%d\n",__LINE__);
+                               fprintf(stderr,"filename=%s\n",name);
+#endif
+                       }
+                       while ( ( name[ 0] != '\0' )
+                        &&     ( name != ( cur_line + (16+so) ) )
+                        && ((     ( name[-1] != ' '  )
+                               || ( name[-6] != ' '  )
+                               || ( name[-9] != ':'  )
+                        )&&(      ( name[-1] != ' '  )
+                               || ( name[-4] != ':'  )
+                               || ( name[-7] != ' '  )
+                               || ( name[-10] != '-'  )
+                               || ( name[-13] != '-'  )
+                        ))
+                       ) name++ ;
+               }
+#ifdef DDS_TRACE
+               fprintf(stderr,"%d\n",__LINE__);
+#endif
+               i = strlen(name) -1 ;
+               if (name[i] == '\n') name[i] = '\0', i-- ;
+               /*
+                * We leave the list of directories empty on quick mode.
+                */
+               if (( name[i] == '/' )&&( quick_mode == 0 )) {
+                       struct dir_list *dp;
+                       for (i = 0 , dp = dl ; i < de; i++ , dp ++ ) {
+                               if (strstr(name, dp->n) != name)
+                                       break;
+                       }
+                       strcpy(dp->n, name);
+                       dp->b = blkno;
+                       dp->r = recno;
+                       de = i + 1 ;
+               }
+               /*
+                * Now we try to match one pattern with the name.
+                */
+#ifdef DDS_TRACE
+               fprintf(stderr,"%d\n",__LINE__);
+               fprintf(stderr,"scanning pattern list for '%s'\n",name);
+#endif
+               p = pattern_list;
+               while (*p != NULL) {
+                       static int ll_blkno = -1 ;
+                       static int ll_recno = -1 ;
+                       static int ln_blkno = -1 ;
+                       static int ln_recno = -1 ;
+                       static const char *ll = "././@LongLink" ;
+#ifdef DDS_TRACE
+                       fprintf(stderr," p = '%p' , *p = %p \n",p,*p);
+#endif
+                       /*
+                        * Thanks Andreas Bagge for this trick.
+                        * I use the fnmatch function from the
+                        * source of gnu tar.
+                        */
+#ifdef DDS_TRACE
+                       fprintf(stderr,"fnmatch '%s' for '%s'\n",name,*p);
+#endif
+                       if (0 == fnmatch(*p, name, FNM_LEADING_DIR)) {
+                               struct dir_list *dp;
+                               for (i = 0, dp = dl; i < de; i++, dp++) {
+                                       char   *p = strstr(name, dp->n);
+                                       if (p == name) {
+                                               extract(dp->n, dp->b, dp->r);
+                                       } else break ;
+                               }
+                               de = 0;
+                               if ( ln_blkno >= 0 ) extract(
+                                               "././@LongLink",
+                                               ln_blkno,
+                                               ln_recno);
+                               if ( ll_blkno >= 0 ) extract(
+                                               "././@LongLink",
+                                               ll_blkno,
+                                               ll_recno);
+                               extract(name, blkno, recno);
+                               break;
+                       }
+                       if ( 0==strncmp(ll,name,strlen(name)) ){
+                               if ( ln_blkno < 0 )
+                               ln_blkno = blkno , ln_recno = recno ;
+                               else
+                               ll_blkno = blkno , ll_recno = recno ;
+                       } else {
+                               ln_blkno = -1 ;
+                               ln_recno = -1 ;
+                               ll_blkno = -1 ;
+                               ll_recno = -1 ;
+                       }
+                       p++;
+               }
+#ifdef DDS_TRACE
+               fprintf(stderr,"end of scanning pattern list\n");
+#endif
+       }
+       /*
+        * Write an empty record to the end of the archive.
+        */
+       memset(cur_block, 0, buf_n );
+       write(1, cur_block, 512);
+       nblocks++;
+       if (verbose)
+               fprintf(stderr, "dds2tar: %d blocks written\n", nblocks);
+#ifdef DDS_TRACE
+       fprintf(stderr,"%d\n",__LINE__);
+       fprintf(stderr,"return of dds_cmp(...)");
+#endif
+       return 0;
+}
diff --git a/dds_index.c b/dds_index.c
new file mode 100644 (file)
index 0000000..9c6949e
--- /dev/null
@@ -0,0 +1,245 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mtio.h>
+#include <unistd.h>
+#include <string.h>
+#include "dds2tar.h"
+#include "dds_tape.h"
+
+static int             cur_rec;
+static int             cur_byte;
+static const   char    hash_sign = '#';
+
+/********
+       * Skip to the next block.
+       *
+       ********************************************************************/
+void dds_index_skip(){
+       /*
+        * The hp-DAT is slowed down with dds_getpos().
+                * Is there a reason for this?
+        *
+        * Now the cur_blkno is incremented.
+        */
+       cur_rec -= cur_bs;
+       dds_read_next_block();
+       cur_byte += cur_n;
+       if (hash_mode == 1)
+               if ((cur_blkno & 0x1f) == 0) {
+                       if ((cur_blkno & 0x7ff) == 0) {
+                               fprintf(stderr, " %d\n",cur_byte);
+                               fflush(stderr);
+                       }
+                       write(2, &hash_sign, 1);
+               }
+}
+
+/********
+       * Converting a tar-record to an entry in the index file.
+       *
+       *  input: tar_record is the header of one file in the archive.
+        *         The location of the header is given by the
+       *         block and index value.
+       * output: The returned index is the location of the next header.
+       *         Normalization of the pair (block,rec) with respect to
+       *         the block length will give the right position.
+       * extern: index_fp, verbose
+       *         index_fp is the FILE to write the rec.
+       *         verbose indicates the loggin mode.
+       *
+       *         If the name length of the file name is zero,
+       *         and an empty block is found, the end
+       *         of the archive is found and the program stops.
+       *
+       ********************************************************************/
+static int
+dds_index_h(tar_record *const ptr, int const block, int rec)
+{
+       int     size;
+       char   *p = ptr->hdr.magic;
+
+#ifdef DDS_TRACE
+       fputs("dds_index_h()\n", stderr);
+#endif
+
+       if ( dds_is_tar_header_record(ptr) == 0 ) {
+               fprintf(stderr,"dds2index: skipping to next header\n");
+               return ( rec + 1 ) ;
+       }
+
+       if (*p == 0)
+               p = "magic ";
+       if (ptr->hdr.linkflag == 'V') p = "label ";
+       else if (p[6] == ' ')
+               p[6] = 0;
+       if (ptr->hdr.name[0] == 0) {
+               int     i = 0;
+
+               while ((((char *) ptr)[i] == 0) && (i < 512))
+                       i++;
+               if (i == 512) {
+                       fprintf(index_fp, dds_index_format,
+                               "-end- ",
+                               block,
+                               rec,
+                               0, "(null)");
+                       close(device);
+                       exit(0);
+               }
+       }
+       if (ptr->hdr.size[0] != 0)
+               sscanf(ptr->hdr.size, "%o", &size);
+       else
+               size = 0;
+       long_name_len = 0 ;
+        if ( ptr->hdr.linkflag == LF_LONGNAME ) long_name_len = size ;
+               
+       {
+               char *name = ptr->hdr.name ;
+               if ( ptr->hdr.linkflag != LF_LONGLINK &&
+                    ptr->hdr.linkflag != LF_LONGNAME &&
+                       long_name[0] != '\0' ) name = long_name ;
+               sprintf(cur_line, dds_index_format,
+                       p,
+                       block,
+                       rec,
+                       size,
+                       name
+                       );
+               fputs(cur_line, index_fp);
+               if ( ptr->hdr.linkflag != LF_LONGLINK &&
+                    ptr->hdr.linkflag != LF_LONGNAME ) {
+                       long_name[0] = '\0' ;
+               }
+       }
+       if (verbose)
+               fputs(cur_line, stderr);
+       /* calculate the number of records */
+       /* there was one header record */
+       size += 511 + 512;
+       size >>= 9;
+       rec += size;
+       return rec;
+}
+
+/********
+        * Converting a table line to the numbers.
+        *
+        */
+int
+rt_line(
+              int *const ptr_blkno,
+              int *const ptr_recno,
+              int *const ptr_size,
+              char **const ptr_name
+)
+{
+       char    p[16];
+       int     i;
+       char    const *dds_fmt = NULL;
+
+#ifdef DDS_TRACE
+       fprintf(stderr,"rt_line(...)\n");
+#endif
+
+       if (cur_line[16] == ':') {
+               dds_fmt = dds_old_index_scan_format ;
+               *ptr_name = cur_line + 27;
+       } else {
+               if (cur_line[17] == ':') {
+                       dds_fmt = dds_index_scan_format ;
+                       *ptr_name = cur_line + 28;
+               } else return 1 ;
+       } ;
+
+       if ((i = sscanf(cur_line,
+                       dds_fmt,
+                       p,
+                       ptr_blkno,
+                       ptr_recno,
+                       ptr_size)) < 4)
+               fprintf(stderr, "Wrong line inside the index file,"
+                       " scanned %d values\n", i);
+#ifdef DDS_TRACE
+       fprintf(stderr,"end >> rt_line(...)\n");
+#endif
+       return 0 ;
+}
+
+/* procedure to create the index table */
+/********
+       *  input: none
+       * output: none
+       * extern: device, index_fp
+       *
+       * The archive is read, and the index file is written.
+       *
+       ************************************************************/
+
+int
+dds_index(void)
+{
+
+
+#ifdef DDS_TRACE
+       fputs("dds_index()\n", stderr);
+#endif
+
+
+       fputs(dds_headline, index_fp);
+       if (verbose) fputs(dds_headline, index_fp);
+       next_blkno = -1 ;
+       cur_rec = 0;
+       dds_read_block();
+       cur_byte = cur_n;
+       if (hash_mode == 1)
+               if ((cur_blkno & 0x1f) == 0) {
+                       write(2, &hash_sign, 1);
+               }
+       while (cur_n > 0) {
+               cur_bs = cur_n >> 9;
+               while (cur_rec < cur_bs) {
+                       int new_rec ;
+                       new_rec = dds_index_h(
+                                                    cur_block + cur_rec,
+                                                    cur_blkno,
+                                                    cur_rec
+                               );
+                       if ( long_name_len > 0 ) {
+                               int i = 0 ;
+                               while ( long_name_len > (i<<9) ){
+                                       cur_rec++;
+                                       /*
+                                        * note: dds_index_skip operates on
+                                        *       cur_rec
+                                        */
+                                       if ( cur_rec >= cur_bs )
+                                               dds_index_skip();
+                                       memcpy(long_name+((i++)<<9),
+                                               cur_block+cur_rec,
+                                               512);
+                               }
+                               long_name_len = 0 ;
+                               /* Now go to the next block behind the
+                                  long name */
+                               cur_rec++;
+                       }
+                       else cur_rec = new_rec ;
+               }
+               dds_index_skip();
+       }
+       if (cur_n <= 0) {
+               perror("dds2tar");
+               fprintf(stderr, "dds_index: unexpected end of tar archive \n");
+               close(device);
+               exit(9);
+       }
+       return 0;
+}
+
diff --git a/dds_quote.c b/dds_quote.c
new file mode 100644 (file)
index 0000000..eecb836
--- /dev/null
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include "dds2tar.h"
+int dds_unquote(char*p){
+       char *q ;
+
+       /* do nothing if there is no quote */
+       while ( *p && *p != '\\' ) p++ ;
+       if ( *p == '\0' ) return 1 ;
+
+       q = p ;
+       while ( *p ){
+               if ( *p == '\\' ) {
+                       char c = p[1] ;
+                       switch (c){
+                               case '\\' : *q++ = '\\'   , p+=2 ; continue ;
+                               case 't'  : *q++ = '\t'   , p+=2 ; continue ;
+                               case 'n'  : *q++ = '\n'   , p+=2 ; continue ;
+                               case 'f'  : *q++ = '\f'   , p+=2 ; continue ;
+                               case 'b'  : *q++ = '\b'   , p+=2 ; continue ;
+                               case 'r'  : *q++ = '\r'   , p+=2 ; continue ;
+                               case '?'  : *q++ = '\177' , p+=2 ; continue ;
+                       }
+                       if ( '0' <= c && c <= '9' ){
+                               int x = 0 ;
+                               int n = 0 ;
+                               sscanf(p+1,"%03o%n",&x,&n);
+                               *q++ = x ; p+=n+1 ; continue ;
+                       }
+                       /*
+                        * Here we should never be, but if, we just proceed.
+                        */
+               }
+               *q++ = *p++ ;
+       }
+       *q++ = '\0' ;
+       return 1 ;
+}
+
+#ifdef TEST_IT
+int main(int argc,char*argv[]){
+       if ( argc < 2 ) return 0 ;
+       dds_unquote(argv[1]);
+       puts(argv[1]);
+       return 0 ;
+}
+#endif
+
diff --git a/dds_tape.c b/dds_tape.c
new file mode 100644 (file)
index 0000000..3b7e526
--- /dev/null
@@ -0,0 +1,475 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ *
+ * Special thanks to Les.Grant@mitsuibabcock.co.uk
+ * for the HP-UX patch.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>             /* fpirntf() */
+#include <errno.h>             /* perror() */
+#include <sys/mtio.h>          /* MTSEEK ... */
+#include <sys/ioctl.h>         /* ioctl() */
+#include <unistd.h>            /* close() exit() */
+#include "dds_tape.h"
+
+#include "dds2tar.h"
+#include "dds_tape.h"
+
+/*
+ * set scsi2logical
+ */
+int dds_scsi2logical(void){
+       struct mtop p ;
+       p.mt_op = MTSETDRVBUFFER ;
+       p.mt_count = MT_ST_OPTIONS|MT_ST_SCSI2LOGICAL ;
+       fputs("scsi2logical\n",stderr);
+       return ioctl(device,MTIOCTOP,&p);
+}
+
+/*
+ * set read_ahead
+ */
+int dds_read_ahead(void){
+       struct mtop p ;
+       int r ;
+       p.mt_op = MTSETDRVBUFFER ;
+       p.mt_count = MT_ST_OPTIONS|MT_ST_READ_AHEAD ;
+       r = ioctl(device,MTIOCTOP,&p);
+#ifdef DDS_TRACE
+       fputs("read_ahead\n",stderr);
+       if ( r < 0 ) perror("Read_ahead");
+#endif
+       return r ;
+}
+
+/*
+ * rewind the last block
+ */
+int dds_bsr(void){
+       struct mtop p ;
+       p.mt_op = MTBSR ;
+       p.mt_count = 1 ;
+       return ioctl(device,MTIOCTOP,&p);
+}
+
+#ifdef MTGETBLK
+/*
+ * get block size
+ */
+int dds_get_bs(void){
+       struct mtop p ;
+       int r ;
+       p.mt_op = MTGETBLK ;
+       p.mt_count = 0 ;
+       r = ioctl(device,MTSETBLK,&p);
+       if ( r >= 0 ) r = p.mt_count ;
+       return r ;
+}
+#endif
+
+/*
+ * set block size
+ */
+int dds_set_bs(int n){
+       struct mtop p ;
+       p.mt_op = MTSETBLK ;
+       p.mt_count = n ;
+       tar_bs = n >> 9 ;
+       tar_n = n ;
+#ifdef DDS_TRACE
+       fprintf(stderr,"record_size=%d\n",n);
+#endif
+       return ioctl(device,MTSETBLK,&p);
+}
+
+/*
+ * To read one line of the device and check for errors, we use the following
+ * code. If a filemark is read, we try the block again.
+ *
+ * Note that cur_blkno and next_blkno is changed.
+ */
+void
+dds_read_next_block(void)
+{
+       int     err = 0;
+
+#ifdef HPDAT
+       if (next_blkno == -1)
+#endif
+               next_blkno = dds_getpos(device);
+       cur_blkno = next_blkno;
+       cur_n = 0;
+#ifdef DDS_TRACE
+       fprintf(stderr, "begin --> read_next_block()\n");
+       fprintf(stderr, "vid=%d \n",vid);
+#endif
+       if ( vid == HP ) do {
+               /* If you write a tape with 'tar -b 256' on SunOS, reading */
+               /* the tape needs the following workaround. SunOS splits the */
+               /* block into three tape blocks of 65534, 65534 and 4 Bytes. */
+               /* dds2tar is reading the tree blocks and the number is */
+               /* the one of the first block. You can not use the tar */
+               /* listing block is this case, because the calculation of the */
+               /* right will fail. Note that 'dds2tar --dds-dd | tar ft -' */
+               /* will show the index of the archive, 'tar t' fails. */
+               /* */
+               /* --dds-dd is in experimental state, so may be I will change */
+               /* this. */
+#if ( ST_BUFFER_BLOCKS > 32 )
+               do {
+                       err = read(device, ((char *) cur_block) + cur_n,
+                                           buf_n - cur_n);
+                       if (err > 0) next_blkno++, cur_n += err;
+               } while ((err > 0) && (cur_n < buf_n) && ((cur_n & 0x1ff) != 0));
+#else
+               err = read(device, cur_block, buf_n);
+               if (err > 0) next_blkno++, cur_n += err ;
+#endif
+               if ((cur_n & 0x1ff) != 0) {
+                       fprintf(stderr, "not a tar archive, record size is"
+                               " %d bytes \n", cur_n);
+                       exit(4);
+               }
+               /*
+                * We are done, if err >= 0.
+                */
+               if ( err >= 0 ) break ;
+
+               /*
+                * If err < 0 ... exit or decrease the buffer ...
+                */
+               if ((errno != EOVERFLOW) || (buf_n == 1)) {
+                       perror("dds2tar");
+                       exit(4);
+               }
+               buf_n >>= 1;
+               fprintf(stderr,"decreasing buffer to %d bytes\n",buf_n);
+               if (buf_n == 1) exit(4);
+       } while ( 1 );
+       if ( vid != HP ) {
+               err = read(device, cur_block, tar_n);
+               if ( err < 0 ) {
+                       fprintf(stderr,
+                       "Can not read from tape with blocksize of %d.\n",
+                       tar_n);
+                       perror("dds2index");
+                       exit(4);
+               }
+               next_blkno += tar_bs , cur_n = err ;
+               if ((cur_n & 0x1ff) != 0) {
+                       fprintf(stderr, "not a tar archive, record size is"
+                               " %d bytes \n", cur_n);
+                       exit(4);
+               }
+       }
+       cur_bs = cur_n >> 9;
+#ifdef DDS_TRACE
+       fprintf(stderr, "end ----> read_next_block()\n");
+#endif
+}
+
+void
+dds_read_block(void)
+{
+       do
+               dds_read_next_block();
+       while (cur_n == 0);
+}
+
+int
+dds_getpos(int const dev)
+{
+       int     i,n;
+
+#ifdef MTIOCPOS
+       struct mtpos pos;
+       i = ioctl(dev, MTIOCPOS, &pos);
+       if (i != 0) {
+               perror("dds2tar: ioctl MTIOCPOS");
+#else
+       i = ioctl(dev, SIOC_GET_POSITION, &n); /* HP-UX */
+       if (i != 0) {
+               perror("dds2tar: ioctl SIOC_GET_POSITION");
+#endif
+               close(dev);
+               exit(11);
+       }
+       n = pos.mt_blkno;
+       if (n < 0) {
+               fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
+               close(dev);
+               exit(12);
+       }
+       return n;
+}
+
+#ifdef MTIOCLOC
+int
+dds_getloc(int const dev)
+{
+       struct mtpos pos;
+       int     i,n;
+
+       i = ioctl(dev, MTIOCPOS, &pos);
+       if (i != 0) {
+               perror("dds2tar: ioctl MTIOCLOC");
+               close(dev);
+               exit(11);
+       }
+       n = pos.mt_blkno;
+       if (n < 0) {
+               fprintf(stderr, "dds2tar: eom detected ? blkno = %d \n", n);
+               close(dev);
+               exit(12);
+       }
+       return n ;
+}
+#endif
+
+int
+dds_has_partitions(int const dev){
+#ifdef MT_ISDDS1
+       struct mtget p ;
+       int i;
+       i = ioctl(dev, MTIOCGET, &p );
+       if ( i >= 0 ) {
+               i = p.mt_type ;
+       } else perror("dds2tar");
+       /*
+       if(i==MT_ISDDS1)fprintf(stderr, "DDS2TAR: drive without partitions\n");
+       if(i==MT_ISDDS2)fprintf(stderr, "DDS2TAR: drive with partitions\n");
+       fprintf(stderr, "DDS2TAR: type = %x\n",i);
+       */
+       return i ;
+#else
+       return -1 ;
+#endif
+}
+
+int
+dds_seek(int const dev, int const blkno)
+{
+       struct mtop op;
+       int     i;
+
+#ifdef SIOC_SET_POSITION
+       i = ioctl(dev, SIOC_SET_POSITION, &blkno);
+#else
+       op.mt_op = MTSEEK;
+       op.mt_count = blkno;
+       i = ioctl(dev, MTIOCTOP, &op);
+#endif
+       if (i != 0) {
+               perror("ioctl SEEK");
+               close(dev);
+               exit(13);
+       }
+       return 0;
+}
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+#ifdef HPDAT
+#include <stdlib.h>            /* malloc() */
+#include <stdio.h>             /* printf() */
+#include <sys/ioctl.h>         /* ioctl() */
+#include <string.h>            /* memset() bcopy() */
+#include <unistd.h>            /* exit() */
+#include "dds_tape.h"
+
+typedef unsigned char byte;
+
+typedef struct {
+       int     inlen;
+       int     outlen;
+       byte    buf[1024];
+}
+
+ioctl_arg;
+
+static void
+copy_page(ioctl_arg * const arg, int const i)
+{
+
+       static struct {
+               char const *const text;
+               int const inlen;
+               int const outlen;
+               byte const buf[32];
+       }
+       const   comp_page[7] =
+       {
+               {
+                       "set_comp_off", 26, 128,
+                       {
+                               0x15, 0x10, 0x00, 0x00,
+                               0x14, 0x00, 0x00, 0x00,
+                               0x10, 0x00, 0x0f, 0x0e,
+                               0x40, 0x80, 0x00, 0x00,
+                               0x00, 0x20, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00
+                       }
+               }
+               ,
+               {
+                       "set_cpmp_on", 26, 128,
+                       {
+                               0x15, 0x10, 0x00, 0x00,
+                               0x14, 0x00, 0x00, 0x00,
+                               0x10, 0x00, 0x0f, 0x0e,
+                               0xc0, 0x80, 0x00, 0x00,
+                               0x00, 0x20, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00,
+                               0x00, 0x00, 0x00, 0x00
+                       }
+               }
+               ,
+               {
+                       "get_comp", 6, 128,
+                       {
+                               0x1a, 0x00, 0x0f, 0x00, 0x40, 0x00
+                       }
+               }
+               ,
+               {
+                       "log_comp", 10, 128,
+                       {
+                               0x4d, 0x00, 0x79, 0x00,
+                               0x00, 0x00, 0x00, 0x00,
+                               0x80, 0x00
+                       }
+               }
+               ,
+               {
+                       "load_tape", 6, 128,
+                       {
+                               0x1b, 0x00, 0x00, 0x00, 0x01, 0x00
+                       }
+               }
+               ,
+               {
+                       "unload_tape", 6, 128,
+                       {
+                               0x1b, 0x00, 0x00, 0x00, 0x00, 0x00
+                       }
+               }
+               ,
+               {
+                       "mode_sense", 6, 128,
+                       {
+                               0x1a, 0x00, 0x00, 0x00, 0x0C, 0x00
+                       }
+               }
+       };
+
+       arg->inlen = comp_page[i].inlen;
+       arg->outlen = comp_page[i].outlen;
+       memset(arg->buf, 0, 1024);
+       bcopy(comp_page[i].buf, arg->buf, arg->inlen);
+}
+
+static int
+print_error(byte const *const b, int len)
+{
+
+       static char const *const sense_key[] =
+       {
+               "no sense", "recovered error", "not ready", "medium error",
+               "hardware error", "illegal request", "unit attention",
+               "data protect", "blank check", "vendor specific",
+               "copy aborted", "aborted command", "equal",
+               "volume overflow", "miscompare", "reserved"
+       };
+
+       int     i;
+
+       if (len > 32)
+               len = 8 + b[7];
+       printf(" err:                ");
+       for (i = 0; i < len; i++)
+               printf(" %2X", b[i]);
+       printf("\n");
+       printf("error sense: %s\n", sense_key[b[2] & 0xf]);
+       printf("asc + ascq = %2x %2x\n", b[12], b[13]);
+       return 0;
+}
+
+void
+set_compression_mode(int dev, int const comp_mode)
+{
+       ioctl_arg *arg;
+
+       if (comp_mode < 0 || comp_mode > 5)
+               return;
+       /*
+        * Allocate memory.
+        */
+       arg = malloc(sizeof (ioctl_arg));
+       if (arg == NULL) {
+               fprintf(stderr, "dds2tar: not enough memory\n");
+               exit(15);
+       }
+       /*
+        * do ioctl
+        */
+       copy_page(arg, comp_mode);
+       /*      arg->buf[12] = (comp_mode << 7) | 0x40; */
+       if (ioctl(dev, 1, arg) != 0) {
+               close(dev);
+               print_error(arg->buf, arg->inlen);
+               exit(16);
+       }
+       if (comp_mode == DDSCM_QUERY) {
+               byte   *b;
+
+               b = arg->buf + 12;
+               fprintf(stderr, "data compression enable %d\n", b[2] >> 7);
+       } else if (comp_mode == DDSCM_LOG) {
+               int     i, j;
+               byte   *b;
+
+               b = arg->buf + 0;
+               for (i = 0; i < b[3];) {
+
+                       static char const *const tab39[] =
+                       {
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                               NULL,
+                               "kilobytes to data compression",
+                               "kilobytes from data compression",
+                               "kilobytes to tape",
+                               "kilobytes from tape",
+                               NULL,
+                               NULL,
+                               NULL};
+
+                       byte   *p = b + i + 4;
+                       int     n, k, c;
+
+                       c = (p[0] << 8) + p[1];
+                       n = p[3];
+                       i += 4 + n;
+                       p += 4;
+                       j = 0;
+                       for (k = 0; k < n; k++)
+                               j = (j << 8) + p[k];
+
+                       if ((c < 12) && (tab39[c] != NULL))
+                               printf("%s: %d\n", tab39[c], j);
+               }
+       }
+}
+
+#endif
diff --git a/dds_tape.h b/dds_tape.h
new file mode 100644 (file)
index 0000000..d21540f
--- /dev/null
@@ -0,0 +1,30 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ */
+
+extern int dds_scsi2logical(void);
+extern int dds_bsr(void);
+extern void dds_read_block(void);
+extern void dds_read_next_block(void);
+extern int dds_getpos(int const dev);
+extern int dds_seek(int const dev ,int const blkno);
+extern int dds_get_bs(void);
+extern int dds_read_ahead(void);
+
+extern int dds_has_partitions(int const dev);
+
+#define DDSCM_NULL -1
+#define DDSCM_OFF 0
+#define DDSCM_ON 1
+#define DDSCM_QUERY 2
+#define DDSCM_LOG 3
+#define DDSCM_LOAD 4
+#define DDSCM_UNLOAD 5
+#define DDSCM_FILENO 6
+#define DDSCM_LOGICAL 7
+#define DDSCM_WHERE 8
+
+extern void set_compression_mode(int _device, const int _mode);
+
diff --git a/ddstool b/ddstool
new file mode 100755 (executable)
index 0000000..fbf20a1
--- /dev/null
+++ b/ddstool
@@ -0,0 +1,87 @@
+#!/bin/sh
+# This tool is in experimental status.
+#
+# Send me an email, if you have nice ideas.
+#                  weule@uni-duesseldorf.de
+#
+#====================================================================
+# Usage:
+#
+# First label a tape:
+#     ddstool create-label 'unique-string and more strings'
+#
+# To archive something:
+#     ddstool append pathnames...
+#
+# To delete the old index-files and make a new label:
+#     ddstool new-label 'unique-string and more strings'
+#
+# Each index is stored by the pathnames:
+#     $A/$unique-string.$file-number              (soft link)
+#     $A/$timestamp-of-the-tapelabel.$file-number (file)
+#
+#====================================================================
+# Sorry that I don't know the right method to extract something.
+# For now it's more save to do it by hand.
+#
+#====================================================================
+#
+set -v
+A=/data/tape
+case "$1" in
+append)
+       mt rewind;
+       L=`mt-dds label | awk '{print $1}' `
+       T=`mt-dds ts`
+       mt rewind
+       mt eom
+       mt status | grep file
+       F=`mt status | awk '{ if ($1 == "file") printf("%02d",$4) }'`
+       echo $A/$T.$F $A/$L.$F
+       touch $A/$T.$F
+       ln -f -s $A/$T.$F $A/$L.$F
+       shift
+       tar --label "$L" -b 32 -R -v -v --record-file $A/$T.$F --create $*
+;;
+create-label)
+       mt rewind
+       tar --create --label "$2" -b 2
+;;
+new-label)
+       mt rewind;
+       L=`mt-dds label | awk '{print $1}' `
+       T=`mt-dds ts`
+       mt rewind
+       rm $A/$L.* $A/$T.*
+       L=`echo "$2" | awk '{print $1}'`
+       if test -f $L.01 ; then
+               echo $0: ERROR: Label ist schon bekannt!
+       else
+               tar --create --label "$2" -b 2
+               mt rewind
+               T=`mt-dds ts`
+               F=00
+               tar -b 1 -t -v -v -R --record-file $A/$T.$F
+               ln -f -s $A/$T.$F $A/$L.$F
+       fi
+;;
+index)
+       mt rewind;
+       L=`mt-dds label | awk '{print $1}' `
+       T=`mt-dds ts`
+       mt rewind
+       B=`mt-dds blksize`
+       echo $B
+       tar -v -v -R -t -b $B --record-file $A/$T.$F
+       mt rewind
+       mt asf "$2"
+       F=`mt status | awk '{ if ($1 == "file") printf("%02d",$4) }'`
+       echo File = $F
+       echo $A/$T.$F $A/$L.$F
+       touch $A/$T.$F
+       ln -f -s $A/$T.$F $A/$L.$F
+       B=`mt-dds blksize`
+       echo Blksize = $B
+       tar -b $B -t -R -v -v --record-file $A/$T.$F
+esac
+mt rewind
diff --git a/index-of-dds2index b/index-of-dds2index
new file mode 100644 (file)
index 0000000..db5a547
--- /dev/null
@@ -0,0 +1,64 @@
+magic  record blk:     size name
+ustar       0   0:        0 ./
+ustar       0   1:     6375 Makefile
+ustar       0  15:    12946 Changes
+ustar       2   2:     7979 README
+ustar       2  19:    11045 dds2tar.man
+ustar       4   2:     2837 dds2index.man
+ustar       4   9:     3919 mt-dds.man
+ustar       4  18:     1666 dds-dd.man
+ustar       5   3:    25773 dds2tar.ps
+ustar       7  15:    10333 dds2index.ps
+ustar       8  17:    11993 mt-dds.ps
+ustar      10   2:     7935 dds-dd.ps
+ustar      10  19:     2388 dds2tar.h
+ustar      11   5:    22264 dds2tar.c
+ustar      13  10:    13073 dds_extract.c
+ustar      14  17:     1141 zf-cre-open.h
+ustar      15   1:     4336 zf-cre-open.c
+ustar      15  11:     5229 dds_index.c
+ustar      16   3:      687 dds_tape.h
+ustar      16   6:     9113 dds_tape.c
+ustar      17   5:      691 dds_chkhdr.c
+ustar      17   8:     1321 scsi_vendor
+ustar      17  12:    10043 tar-1.11.2.patch
+ustar      18  13:    14757 tar-1.11.8.patch
+ustar      20   3:    14579 tar-1.12.patch
+ustar      21  13:      294 tar-1.11.2-sparse-files.patch
+ustar      21  15:      353 tar-1.11.2-sparse-files.README
+ustar      21  17:     4961 dds2tar-test.sh
+ustar      22   8:        0 dds2index
+ustar      22   9:        0 mt-dds
+ustar      22  10:        0 dds2tar-test-tape-link-soft
+ustar      22  11:      100 .indent.pro
+ustar      22  13:     1276 dds2tar.lsm
+ustar      22  17:    17982 COPYING
+ustar      24  14:     2104 ddstool
+ustar      25   0:      422 e.c
+ustar      25   2:    10240 x.tar
+ustar      26   3:        0 tdir/
+ustar      26   4:        0 tdir/ä.txt
+ustar      26   5:    11890 e
+ustar      27  10:    12579 dds_quote
+ustar      28  16:     1010 dds_quote.c
+ustar      28  19:    62720 dds2tar.o
+ustar      35   3:    22492 dds_index.o
+ustar      37   8:    28448 dds_extract.o
+ustar      40   5:    25844 dds_tape.o
+ustar      42  17:    11344 dds_quote.o
+ustar      44   1:    24180 zf-cre-open.o
+ustar      46  10:    17288 dds_chkhdr.o
+ustar      48   5:   119244 dds2tar
+ustar      59  19:        0 dds2tar-test-tape-link-hard
+ustar      60   0:        0 dds-dd
+ustar      60   1:    11045 dds2tar.1
+ustar      61   4:     2837 dds2index.1
+ustar      61  11:     3919 mt-dds.1
+ustar      62   0:     1666 dds-dd.1
+ustar      62   5:    15888 tar-1.13.patch
+ustar      63  18:      131 ././@LongLink
+ustar      64   0:        0 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ustar      64   1:      131 ././@LongLink
+ustar      64   3:      141 ././@LongLink
+ustar      64   5:        0 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+-end-      64   6:        0 (null)
diff --git a/index-of-tar b/index-of-tar
new file mode 100644 (file)
index 0000000..30f64c9
--- /dev/null
@@ -0,0 +1,66 @@
+loc             number of the file is 1 
+loc             number of the first block is 65
+loc             block length is 16384 bytes = 32 * 512 bytes
+rec          0: block 0: dds2tar
+rec          1: block 1: ./
+rec          2: block 2: Makefile
+rec         16: block 16: Changes
+rec         11: block 43: README
+rec         28: block 60: dds2tar.man
+rec         19: block 83: dds2index.man
+rec         26: block 90: mt-dds.man
+rec          3: block 99: dds-dd.man
+rec          8: block 104: dds2tar.ps
+rec         28: block 156: dds2index.ps
+rec         18: block 178: mt-dds.ps
+rec         11: block 203: dds-dd.ps
+rec         28: block 220: dds2tar.h
+rec          2: block 226: dds2tar.c
+rec         15: block 271: dds_extract.c
+rec         10: block 298: zf-cre-open.h
+rec         14: block 302: zf-cre-open.c
+rec         24: block 312: dds_index.c
+rec          4: block 324: dds_tape.h
+rec          7: block 327: dds_tape.c
+rec         26: block 346: dds_chkhdr.c
+rec         29: block 349: scsi_vendor
+rec          1: block 353: tar-1.11.2.patch
+rec         22: block 374: tar-1.11.8.patch
+rec         20: block 404: tar-1.12.patch
+rec         18: block 434: tar-1.11.2-sparse-files.patch
+rec         20: block 436: tar-1.11.2-sparse-files.README
+rec         22: block 438: dds2tar-test.sh
+rec          1: block 449: dds2index
+rec          2: block 450: mt-dds
+rec          3: block 451: dds2tar-test-tape-link-soft
+rec          4: block 452: .indent.pro
+rec          6: block 454: dds2tar.lsm
+rec         10: block 458: COPYING
+rec         15: block 495: ddstool
+rec         21: block 501: e.c
+rec         23: block 503: x.tar
+rec         12: block 524: tdir/
+rec         13: block 525: tdir/\344.txt
+rec         14: block 526: e
+rec          7: block 551: dds_quote
+rec          1: block 577: dds_quote.c
+rec          4: block 580: dds2tar.o
+rec          0: block 704: dds_index.o
+rec         13: block 749: dds_extract.o
+rec          6: block 806: dds_tape.o
+rec         26: block 858: dds_quote.o
+rec         18: block 882: zf-cre-open.o
+rec          3: block 931: dds_chkhdr.o
+rec          6: block 966: dds2tar
+rec         16: block 1200: dds2tar-test-tape-link-hard
+rec         17: block 1201: dds-dd
+rec         18: block 1202: dds2tar.1
+rec          9: block 1225: dds2index.1
+rec         16: block 1232: mt-dds.1
+rec         25: block 1241: dds-dd.1
+rec         30: block 1246: tar-1.13.patch
+rec         31: block 1279: ././@LongLink
+rec          1: block 1281: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+rec          2: block 1282: ././@LongLink
+rec          4: block 1284: ././@LongLink
+rec          6: block 1286: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
diff --git a/index-of-tar-t b/index-of-tar-t
new file mode 100644 (file)
index 0000000..310cd14
--- /dev/null
@@ -0,0 +1,68 @@
+first block number is 0
+block size is 20
+block length is 10240
+loc             number of the file is 0 
+loc             number of the first block is 0
+rec          0: block 0: ./
+rec          1: block 1: Makefile
+rec         15: block 15: Changes
+rec          2: block 42: README
+rec         19: block 59: dds2tar.man
+rec          2: block 82: dds2index.man
+rec          9: block 89: mt-dds.man
+rec         18: block 98: dds-dd.man
+rec          3: block 103: dds2tar.ps
+rec         15: block 155: dds2index.ps
+rec         17: block 177: mt-dds.ps
+rec          2: block 202: dds-dd.ps
+rec         19: block 219: dds2tar.h
+rec          5: block 225: dds2tar.c
+rec         10: block 270: dds_extract.c
+rec         17: block 297: zf-cre-open.h
+rec          1: block 301: zf-cre-open.c
+rec         11: block 311: dds_index.c
+rec          3: block 323: dds_tape.h
+rec          6: block 326: dds_tape.c
+rec          5: block 345: dds_chkhdr.c
+rec          8: block 348: scsi_vendor
+rec         12: block 352: tar-1.11.2.patch
+rec         13: block 373: tar-1.11.8.patch
+rec          3: block 403: tar-1.12.patch
+rec         13: block 433: tar-1.11.2-sparse-files.patch
+rec         15: block 435: tar-1.11.2-sparse-files.README
+rec         17: block 437: dds2tar-test.sh
+rec          8: block 448: dds2index
+rec          9: block 449: mt-dds
+rec         10: block 450: dds2tar-test-tape-link-soft
+rec         11: block 451: .indent.pro
+rec         13: block 453: dds2tar.lsm
+rec         17: block 457: COPYING
+rec         14: block 494: ddstool
+rec          0: block 500: e.c
+rec          2: block 502: x.tar
+rec          3: block 523: tdir/
+rec          4: block 524: tdir/\344.txt
+rec          5: block 525: e
+rec         10: block 550: dds_quote
+rec         16: block 576: dds_quote.c
+rec         19: block 579: dds2tar.o
+rec          3: block 703: dds_index.o
+rec          8: block 748: dds_extract.o
+rec          5: block 805: dds_tape.o
+rec         17: block 857: dds_quote.o
+rec          1: block 881: zf-cre-open.o
+rec         10: block 930: dds_chkhdr.o
+rec          5: block 965: dds2tar
+rec         19: block 1199: dds2tar-test-tape-link-hard
+rec          0: block 1200: dds-dd
+rec          1: block 1201: dds2tar.1
+rec          4: block 1224: dds2index.1
+rec         11: block 1231: mt-dds.1
+rec          0: block 1240: dds-dd.1
+rec          5: block 1245: tar-1.13.patch
+rec         18: block 1278: ././@LongLink
+rec          0: block 1280: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+rec          1: block 1281: ././@LongLink
+rec          3: block 1283: ././@LongLink
+rec          5: block 1285: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+block 1286: ** Block of NULs **
diff --git a/index-of-tar-v b/index-of-tar-v
new file mode 100644 (file)
index 0000000..1f3d60a
--- /dev/null
@@ -0,0 +1,65 @@
+loc             number of the file is 2 
+loc             number of the first block is 106
+loc             block length is 16384 bytes = 32 * 512 bytes
+rec          0: block 0: drwxr-x--- weule/users       0 2000-08-17 00:16 ./
+rec          1: block 1: -rw-r----- weule/users    6375 2000-08-17 00:15 Makefile
+rec         15: block 15: -rw-r----- weule/users   12946 2000-08-13 15:15 Changes
+rec         10: block 42: -rw-r----- weule/users    7979 1998-06-23 12:11 README
+rec         27: block 59: -rw-r----- weule/users   11045 1998-02-02 16:40 dds2tar.man
+rec         18: block 82: -rw-r----- weule/users    2837 1995-02-01 23:33 dds2index.man
+rec         25: block 89: -rw-r----- weule/users    3919 1995-02-01 23:34 mt-dds.man
+rec          2: block 98: -rw-r----- weule/users    1666 1996-03-10 17:05 dds-dd.man
+rec          7: block 103: -rw-r----- weule/users   25773 1998-02-02 16:42 dds2tar.ps
+rec         27: block 155: -rw-r----- weule/users   10333 1996-03-10 17:12 dds2index.ps
+rec         17: block 177: -rw-r----- weule/users   11993 1996-03-10 17:12 mt-dds.ps
+rec         10: block 202: -rw-r----- weule/users    7935 1996-03-10 17:12 dds-dd.ps
+rec         27: block 219: -rw-r----- weule/users    2388 2000-08-06 17:42 dds2tar.h
+rec          1: block 225: -rw-r----- weule/users   22264 2000-08-13 15:27 dds2tar.c
+rec         14: block 270: -rw-r----- weule/users   13073 2000-08-06 17:54 dds_extract.c
+rec          9: block 297: -rw-r----- weule/users    1141 2000-08-06 17:42 zf-cre-open.h
+rec         13: block 301: -rw-r----- weule/users    4336 2000-08-06 17:42 zf-cre-open.c
+rec         23: block 311: -rw-r----- weule/users    5229 2000-08-06 17:42 dds_index.c
+rec          3: block 323: -rw-r----- weule/users     687 2000-08-06 17:42 dds_tape.h
+rec          6: block 326: -rw-r----- weule/users    9113 2000-08-06 17:42 dds_tape.c
+rec         25: block 345: -rw-r----- weule/users     691 2000-08-06 17:42 dds_chkhdr.c
+rec         28: block 348: -rwxr-x--- weule/users    1321 1998-05-15 14:56 scsi_vendor
+rec          0: block 352: -rw-r----- weule/users   10043 1995-02-09 23:14 tar-1.11.2.patch
+rec         21: block 373: -rw-r----- weule/users   14757 1996-12-01 16:22 tar-1.11.8.patch
+rec         19: block 403: -rw-r----- weule/users   14579 2000-08-06 22:21 tar-1.12.patch
+rec         17: block 433: -rw-r----- weule/users     294 1995-02-02 21:56 tar-1.11.2-sparse-files.patch
+rec         19: block 435: -rw-r----- weule/users     353 1995-02-02 22:06 tar-1.11.2-sparse-files.README
+rec         21: block 437: -rwxr-x--- weule/users    4961 2000-08-13 15:45 dds2tar-test.sh
+rec          0: block 448: lrwxrwxrwx weule/users       0 2000-08-17 00:16 dds2index -> ./dds2tar
+rec          1: block 449: lrwxrwxrwx weule/users       0 2000-08-17 00:16 mt-dds -> ./dds2tar
+rec          2: block 450: lrwxrwxrwx weule/users       0 2000-08-17 00:16 dds2tar-test-tape-link-soft -> dds2tar
+rec          3: block 451: -rw-r----- weule/users     100 1994-10-09 23:21 .indent.pro
+rec          5: block 453: -rw-r----- weule/users    1276 2000-08-17 00:12 dds2tar.lsm
+rec          9: block 457: -rw-r----- weule/users   17982 1994-09-03 13:40 COPYING
+rec         14: block 494: -rwxr-x--- weule/users    2104 1995-02-05 23:51 ddstool
+rec         20: block 500: -rw-r----- weule/users     422 2000-08-06 17:42 e.c
+rec         22: block 502: -rw-r----- weule/users   10240 2000-08-06 14:32 x.tar
+rec         11: block 523: drwxr-x--- weule/users       0 2000-08-06 16:24 tdir/
+rec         12: block 524: -rw-r----- weule/users       0 2000-08-06 16:24 tdir/\344.txt
+rec         13: block 525: -rwxr-x--- weule/users   11890 2000-08-06 15:01 e
+rec          6: block 550: -rwxr-x--- weule/users   12579 2000-08-06 15:52 dds_quote
+rec          0: block 576: -rw-r----- weule/users    1010 2000-08-06 17:42 dds_quote.c
+rec          3: block 579: -rw-r----- weule/users   62720 2000-08-13 15:30 dds2tar.o
+rec         31: block 703: -rw-r----- weule/users   22492 2000-08-06 17:42 dds_index.o
+rec         12: block 748: -rw-r----- weule/users   28448 2000-08-06 17:54 dds_extract.o
+rec          5: block 805: -rw-r----- weule/users   25844 2000-08-06 17:42 dds_tape.o
+rec         25: block 857: -rw-r----- weule/users   11344 2000-08-06 17:42 dds_quote.o
+rec         17: block 881: -rw-r----- weule/users   24180 2000-08-06 17:42 zf-cre-open.o
+rec          2: block 930: -rw-r----- weule/users   17288 2000-08-06 17:42 dds_chkhdr.o
+rec          5: block 965: -rwxr-x--- weule/users  119244 2000-08-13 15:30 dds2tar
+rec         15: block 1199: -rwxr-x--- weule/users       0 2000-08-13 15:30 dds2tar-test-tape-link-hard link to dds2tar
+rec         16: block 1200: -rwxr-x--- weule/users       0 2000-08-13 15:30 dds-dd link to dds2tar
+rec         17: block 1201: -rw-r--r-- weule/users   11045 2000-08-06 15:56 dds2tar.1
+rec          8: block 1224: -rw-r--r-- weule/users    2837 2000-08-06 15:56 dds2index.1
+rec         15: block 1231: -rw-r--r-- weule/users    3919 2000-08-06 15:56 mt-dds.1
+rec         24: block 1240: -rw-r--r-- weule/users    1666 2000-08-06 15:56 dds-dd.1
+rec         29: block 1245: -rw-r----- weule/users   15888 2000-08-06 23:39 tar-1.13.patch
+rec         30: block 1278: Lrw-r----- root/root         0 2000-08-06 20:57 ././@LongLink unknown file type `L'
+rec          0: block 1280: -rw-r----- weule/users       0 2000-08-06 20:57 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+rec          1: block 1281: Krwxrwxrwx root/root       130 2000-08-06 20:57 ././@LongLink unknown file type `K'
+rec          3: block 1283: Lrwxrwxrwx root/root         0 2000-08-06 20:57 ././@LongLink unknown file type `L'
+rec          5: block 1285: lrwxrwxrwx weule/users       0 2000-08-06 20:57 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 -> 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
diff --git a/mt-dds.man b/mt-dds.man
new file mode 100644 (file)
index 0000000..c4fef84
--- /dev/null
@@ -0,0 +1,174 @@
+.TH mt-dds 1L 2.4 \" -*- nroff -*-
+.\"----------
+.SH NAME
+.\"----------
+mt-dds \- tool to control a dds device.
+.\"----------
+.SH SYNOPSIS
+.\"----------
+.B mt-dds
+.BR comp-on | comp-off | comp-query | comp-log 
+.PD 0
+.PP
+.B mt-dds
+<
+.BR tell | label
+> [
+.B -b \ #
+]
+.PD 1
+.\"----------
+.SH DESCRIPTION
+.\"----------
+.B mt-dds
+controls the compression mode of dds tape devices (DAT).
+.PP
+.B mt-dds
+may also report the current tape position in
+absolute records (relative to begin of tape) in a format
+that may be used later by 
+.B dds2tar(1)
+to access tar archives that are not the first file on tape.
+.PP
+The default device is
+.IR /dev/tape ,
+which may be overridden with the environment variable
+.BR TAPE ,
+which in turn may be overridden with the
+.BI -f \ device
+option. The device must be a character special file.
+.\"----------
+.SH OPTIONS
+.\"----------
+.SS DDS tape device control options
+
+.TP
+.B comp-on
+Enable the hardware compression mode if supported by the device.
+.TP 
+.B comp-off
+Disable the compression mode, switch to normal mode.
+.TP 
+.B comp-query
+Print to stderr if compression mode currently is disabled 
+or enabled.  A 
+.B 0
+means compression is disabled, a
+.B 1
+means compression in enabled.
+.TP 
+.B comp-log
+Print to stdout four lines of information about transferred kilobytes 
+before and after hardware compression from and to the device
+since initialization.
+.\"----------
+.SS dds2tar service functions
+
+.TP
+.B tell
+Print three lines with the 
+.BR "current tape position" ", a" 
+.B block size 
+value (20 by default, may be overridden with 
+.B -b
+option) and a 
+.B block length
+value (blocksize*512) to 
+.IR stdout .
+If this output is redirected to a location file 
+.IR locfile ,
+this file may be used by 
+.B dds2tar(1)
+to access archives on tape.
+.TP
+.B label
+If the current tape position is the beginning of an archive and the archive
+is labeled,
+.B mt-dds
+writes the label to stdout
+and moves the tape back to the
+current position (or back over the filemark).
+.TP
+.B ts
+If the current tape position is the beginning of an archive and the archive
+is labeled,
+.B mt-dds
+writes the timestamp in octal format to stdout
+and moves the tape back to the
+current position (or back over the filemark).
+If you are using only one computer, the timestamp can be used as a unique
+archive identifier.
+.TP
+.BI -b \  #
+Specify the block size 
+.I #
+value that is used as a default for the written value with the
+.B mt-dds tell
+command (see above).
+Also the internal buffer size is specified with this option
+which is used to read one block in order to get the block size
+of the current tape block. So specify the block size of the archive
+or a larger number.
+.\"----------
+.SS other options
+
+.TP
+.BI -f\  device
+Device of the tape archive (default is /dev/tape).
+Must be a character special file connected to a dds tape device.
+.TP
+.BR -V , --version
+Print the version number of
+.B mt-dds
+to stderr and exit immediately.
+.TP
+.B --help
+print some screens of online help with examples through a pager
+and exit immediately.
+.\"----------
+.SH EXAMPLES
+.\"----------
+.B Example 1: 
+checking the compression mode of the default tape device
+.RS 10
+mt-dds comp-query
+.RE
+.PP
+.B Example 2: 
+Write the location information as
+.B dds2tar
+command line options to stdout.
+.RS 10
+mt-dds
+.RE
+.PP
+.PD 1
+.\"----------
+.SH ENVIRONMENT
+.\"----------
+The environment variable
+.B TAPE
+overrides the default tape device /dev/tape.
+.TP
+PAGER
+The environment variable
+.B PAGER
+overrides the builtin pager command ("/bin/more") to display the output
+of the
+.B --help
+option.
+.\"----------
+.SH "SEE ALSO"
+.\"----------
+dds2tar(1), dds2index(1), mt(1), tar(1)
+.\"----------
+.SH HISTORY
+.\"----------
+This program was created to use it in conjunction with dds2tar.
+.\"----------
+.SH AUTHOR
+.\"----------
+J"org Weule (weule@cs.uni-duesseldorf.de), Phone +49 211 751409.
+This software is available at
+ftp.uni-duesseldorf.de:/pub/unix/apollo
+
diff --git a/mt-dds.ps b/mt-dds.ps
new file mode 100644 (file)
index 0000000..2d26458
--- /dev/null
+++ b/mt-dds.ps
@@ -0,0 +1,313 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.09
+%%CreationDate: Sun Mar 10 17:12:17 1996
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Bold
+%%+ font Times-Italic
+%%DocumentSuppliedResources: procset grops 1.09 0
+%%Pages: 2
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.09 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Italic
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
+def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
+/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
+/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
+/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
+/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
+/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
+/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
+/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
+/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
+/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
+/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
+/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
+/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
+/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
+/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
+/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
+/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
+/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
+/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
+/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
+/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 374.4(mt-dds\(1L\) mt-dds\(1L\))72 48 R/F1 9
+/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0
+(mt-dds \255 tool to control a dds de)108 96 Q(vice.)-.25 E F1(SYNOPSIS)
+72 112.8 Q/F2 10/Times-Bold@0 SF(mt-dds comp-on)108 124.8 Q F0(|)A F2
+(comp-off)A F0(|)A F2(comp-query)A F0(|)A F2(comp-log)A(mt-dds)108 136.8
+Q F0(<)2.5 E F2(tell)2.5 E F0(|)A F2(label)A F0 2.5(>[)2.5 G F2 2.5
+(-b #)B F0(])2.5 E F1(DESCRIPTION)72 160.8 Q F2(mt-dds)108 172.8 Q F0
+(controls the compression mode of dds tape de)2.5 E(vices \(D)-.25 E
+-1.11(AT)-.4 G(\).)1.11 E F2(mt-dds)108 196.8 Q F0 .547
+(may also report the current tape position in absolute records \(relati)
+3.048 F .847 -.15(ve t)-.25 H 3.047(ob).15 G -.15(eg)-3.047 G .547
+(in of tape\) in a format).15 F(that may be used later by)108 208.8 Q F2
+(dds2tar\(1\))2.5 E F0(to access tar archi)2.5 E -.15(ve)-.25 G 2.5(st)
+.15 G(hat are not the \214rst \214le on tape.)-2.5 E .726(The def)108
+232.8 R .726(ault de)-.1 F .726(vice is)-.25 F/F3 10/Times-Italic@0 SF
+(/de)3.226 E(v/rmt0)-.15 E F0 3.226(,w).47 G .726(hich may be o)-3.226 F
+-.15(ve)-.15 G .726(rridden with the en).15 F .726(vironment v)-.4 F
+(ariable)-.25 E F2 -.9(TA)3.226 G(PE).9 E F0 3.226(,w)C .726(hich in)
+-3.226 F(turn may be o)108 244.8 Q -.15(ve)-.15 G(rridden with the).15 E
+F2(-f)2.5 E F3(de)2.5 E(vice)-.15 E F0(option. The de)2.5 E
+(vice must be a character special \214le.)-.25 E F1(OPTIONS)72 268.8 Q
+F2(DDS tape de)87 280.8 Q(vice contr)-.15 E(ol options)-.18 E(comp-on)
+108 292.8 Q F0(Enable the hardw)144 304.8 Q
+(are compression mode if supported by the de)-.1 E(vice.)-.25 E F2
+(comp-off)108 328.8 Q F0
+(Disable the compression mode, switch to normal mode.)144 340.8 Q F2
+(comp-query)108 364.8 Q F0 .94
+(Print to stderr if compression mode currently is disabled or enabled.)
+144 376.8 R(A)5.94 E F2(0)3.44 E F0 .94(means compression is)3.44 F
+(disabled, a)144 388.8 Q F2(1)2.5 E F0(means compression in enabled.)2.5
+E F2(comp-log)108 412.8 Q F0 .005(Print to stdout four lines of informa\
+tion about transferred kilobytes before and after hardw)144 424.8 R .005
+(are com-)-.1 F(pression from and to the de)144 436.8 Q
+(vice since initialization.)-.25 E F2(dds2tar ser)87 460.8 Q
+(vice functions)-.1 E(tell)108 472.8 Q F0 .095
+(Print three lines with the)22.67 F F2(curr)2.594 E .094
+(ent tape position)-.18 F F0 2.594(,a)C F2 .094(block size)B F0 -.25(va)
+2.594 G .094(lue \(20 by def).25 F .094(ault, may be o)-.1 F -.15(ve)
+-.15 G(rrid-).15 E .002(den with)144 484.8 R F2(-b)2.502 E F0 .002
+(option\) and a)2.502 F F2 .002(block length)2.502 F F0 -.25(va)2.502 G
+.003(lue \(blocksize*512\) to).25 F F3(stdout)2.503 E F0 5.003(.I).68 G
+2.503(ft)-5.003 G .003(his output is redirected)-2.503 F
+(to a location \214le)144 496.8 Q F3(loc\214le)2.5 E F0 2.5(,t).18 G
+(his \214le may be used by)-2.5 E F2(dds2tar\(1\))2.5 E F0
+(to access archi)2.5 E -.15(ve)-.25 G 2.5(so).15 G 2.5(nt)-2.5 G(ape.)
+-2.5 E F2(label)108 520.8 Q F0 .217
+(If the current tape position is the be)15.44 F .217
+(ginning of an archi)-.15 F .517 -.15(ve a)-.25 H .217(nd the archi).15
+F .517 -.15(ve i)-.25 H 2.717(sl).15 G(abeled,)-2.717 E F2(mt-dds)2.717
+E F0(writes)2.717 E(the label to stdout and mo)144 532.8 Q -.15(ve)-.15
+G 2.5(st).15 G(he tape back to the current position \(or back o)-2.5 E
+-.15(ve)-.15 G 2.5(rt).15 G(he \214lemark\).)-2.5 E F2(ts)108 556.8 Q F0
+.217(If the current tape position is the be)28.78 F .217
+(ginning of an archi)-.15 F .517 -.15(ve a)-.25 H .217(nd the archi).15
+F .517 -.15(ve i)-.25 H 2.717(sl).15 G(abeled,)-2.717 E F2(mt-dds)2.717
+E F0(writes)2.718 E .847(the timestamp in octal format to stdout and mo)
+144 568.8 R -.15(ve)-.15 G 3.347(st).15 G .847
+(he tape back to the current position \(or back)-3.347 F -.15(ove)144
+580.8 S 3.617(rt).15 G 1.117(he \214lemark\).)-3.617 F 1.117
+(If you are using only one computer)6.117 F 3.617(,t)-.4 G 1.117
+(he timestamp can be used as a unique)-3.617 F(archi)144 592.8 Q .3 -.15
+(ve i)-.25 H(denti\214er).15 E(.)-.55 E F2(-b #)108 616.8 Q F0 .746
+(Specify the block size)19.61 F F3(#)3.246 E F0 -.25(va)3.246 G .745
+(lue that is used as a def).25 F .745(ault for the written v)-.1 F .745
+(alue with the)-.25 F F2 .745(mt-dds tell)3.245 F F0 .633
+(command \(see abo)144 628.8 R -.15(ve)-.15 G 3.133(\). Also).15 F .633
+(the internal b)3.133 F(uf)-.2 E .633
+(fer size is speci\214ed with this option which is used to)-.25 F .263(\
+read one block in order to get the block size of the current tape block\
+. So specify the block size of)144 640.8 R(the archi)144 652.8 Q .3 -.15
+(ve o)-.25 H 2.5(ral).15 G(ar)-2.5 E(ger number)-.18 E(.)-.55 E F2
+(other options)87 676.8 Q(-f)108 688.8 Q F3(de)2.85 E(vice)-.15 E F0(De)
+144 700.8 Q .791(vice of the tape archi)-.25 F 1.091 -.15(ve \()-.25 H
+(def).15 E .791(ault is /de)-.1 F 3.291(v/rmt0\). Must)-.25 F .792
+(be a character special \214le connected to a)3.291 F(dds tape de)144
+712.8 Q(vice.)-.25 E 220.25(2.4 1)299.75 768 R EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF 374.4(mt-dds\(1L\) mt-dds\(1L\))72 48 R/F1 10
+/Times-Bold@0 SF(-V)108 84 Q F0(,)A F1(--v)A(ersion)-.1 E F0
+(Print the v)144 96 Q(ersion number of)-.15 E F1(mt-dds)2.5 E F0
+(to stderr and e)2.5 E(xit immediately)-.15 E(.)-.65 E F1(--help)108 120
+Q F0(print some screens of online help with e)11 E
+(xamples through a pager and e)-.15 E(xit immediately)-.15 E(.)-.65 E/F2
+9/Times-Bold@0 SF(EXAMPLES)72 144 Q F1(Example 1:)108 156 Q F0
+(checking the compression mode of the def)2.5 E(ault tape de)-.1 E(vice)
+-.25 E(mt-dds comp-query)158 168 Q F1(Example 2:)108 192 Q F0
+(Write the location information as)2.5 E F1(dds2tar)2.5 E F0
+(command line options to stdout.)2.5 E(mt-dds)158 204 Q F2(ENVIR)72 240
+Q(ONMENT)-.27 E F0(The en)108 252 Q(vironment v)-.4 E(ariable)-.25 E F1
+-.9(TA)2.5 G(PE).9 E F0 -.15(ove)2.5 G(rrides the def).15 E
+(ault tape de)-.1 E(vice /de)-.25 E(v/rmt0.)-.25 E -1.06 -.92(PA G)108
+276 T(ER).92 E .914(The en)144 288 R .914(vironment v)-.4 F(ariable)-.25
+E F1 -1.57 -.74(PA G)3.414 H(ER).74 E F0 -.15(ove)3.414 G .914
+(rrides the b).15 F .913
+(uiltin pager command \("/bin/more"\) to display)-.2 F
+(the output of the)144 300 Q F1(--help)2.5 E F0(option.)2.5 E F2
+(SEE ALSO)72 324 Q F0(dds2tar\(1\), dds2inde)108 336 Q
+(x\(1\), mt\(1\), tar\(1\))-.15 E F2(HIST)72 360 Q(OR)-.162 E(Y)-.315 E
+F0(This program w)108 372 Q(as created in conjunction with dds2tar)-.1 E
+(.)-.55 E F2 -.45(AU)72 396 S(THOR).45 E F0(J"or)108 408 Q 3.028(gW)-.18
+G .528(eule \(weule@cs.uni-duesseldorf.de\), Phone +49 211 751409.)
+-3.828 F .528(This softw)5.528 F .529(are is a)-.1 F -.25(va)-.2 G .529
+(ilable at ftp.uni-).25 F(duesseldorf.de:/pub/unix/apollo)108 420 Q
+220.25(2.4 2)299.75 768 R EP
+%%Trailer
+end
+%%EOF
diff --git a/scsi_vendor b/scsi_vendor
new file mode 100755 (executable)
index 0000000..ab96153
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/csh
+# 
+# Determine the Verndor of a device
+#
+# csh-Example:
+#
+#      <1>scsi_vendor
+#      Disks: SEAGATE SAMSUNG
+#      Cdroms: TOSHIBA PHILIPS
+#      Tapes: HP
+#      <2>scsi_vendor disk
+#      SEAGATE SAMSUNG
+#      <383>scsi_vendor cd
+#      TOSHIBA PHILIPS
+#      <3>scsi_vendor tape 
+#      HP
+#      <4>scsi_vendor tape 1
+#      HP
+#      <5>scsi_vendor dsik 1
+#      <6>scsi_vendor disk 1
+#      SEAGATE
+#      <7>scsi_vendor disk 2
+#      SAMSUNG
+#
+set s = ( ) ;
+set c = ( ) ;
+set d = ( ) ;
+set x = ( `grep '^ ' /proc/scsi/scsi | cut -c3-18` )
+set o = '' ;
+set v = '' ;
+foreach i ( $x )
+       if ( "$o" == 'Vendor:' ) set v = $i ;
+       if ( "$o" == 'Type:' && "$i" == 'Sequenti' ) set s = ( $s $v );
+       if ( "$o" == 'Type:' && "$i" == 'CD-ROM' ) set c = ( $c $v );
+       if ( "$o" == 'Type:' && "$i" == 'Direct-A' ) set d = ( $d $v );
+       set o = $i ;
+end
+if ( $# == 0 ) then
+       echo Disks: $d
+       echo Cdroms: $c
+       echo Tapes: $s
+       exit 0 ;
+endif
+if ( $# == 1 ) then
+       set v = '' ;
+       if ( $1 == disk ) then
+               echo $d
+       endif
+       if ( $1 == cd ) then
+               echo $c
+       endif
+       if ( $1 == tape ) then
+               echo $s
+       endif
+       exit 0 ;
+endif
+if ( $# == 2 ) then
+       set v = '' ;
+       if ( $1 == disk && $#d >= $2 ) then
+               set v = $d[$2] ;
+       endif
+       if ( $1 == cd && $#c >= $2 ) then
+               set v = $c[$2] ;
+       endif
+       if ( $1 == tape && $#s >= $2 ) then
+               set v = $s[$2] ;
+       endif
+       echo $v
+       exit 0 ;
+endif
+if ( "$v" == "$3" ) then
+       exit 2 ;
+endif
+exit 1 ;
+
diff --git a/tar-1.11.2-sparse-files.README b/tar-1.11.2-sparse-files.README
new file mode 100644 (file)
index 0000000..410a8b0
--- /dev/null
@@ -0,0 +1,9 @@
+Michael Riepe (riepe@ifwsn4.ifw.uni-hannover.de) has send me a patch
+to support sparse files with tar on Linux boxes.
+
+I did'nt have any experience with it and unfortunately dds2tar doesn't support
+sparse files. But if you are familar with patching tar, you may decide
+to include this patch also.
+
+Please send comments on that patch to Michael. J"org.
+
diff --git a/tar-1.11.2-sparse-files.patch b/tar-1.11.2-sparse-files.patch
new file mode 100644 (file)
index 0000000..4edefa6
--- /dev/null
@@ -0,0 +1,12 @@
+diff -ru tar-1.11.2/create.c tar-1.11.2.1/create.c
+--- tar-1.11.2/create.c        Thu Mar 25 19:32:31 1993
++++ tar-1.11.2.1/create.c      Wed Oct 26 01:11:39 1994
+@@ -380,7 +380,7 @@
+       header_moved = 0;
+-#ifdef BSD42
++#if defined(BSD42) || defined(__linux__)
+       if (f_sparse_files)
+       {
+         /*
diff --git a/tar-1.11.2.patch b/tar-1.11.2.patch
new file mode 100644 (file)
index 0000000..2ab19f1
--- /dev/null
@@ -0,0 +1,344 @@
+diff -ru tar-1.11.2/ChangeLog tar-1.11.2.1/ChangeLog
+--- tar-1.11.2/ChangeLog       Thu Mar 25 19:54:56 1993
++++ tar-1.11.2.1/ChangeLog     Mon Oct  3 21:07:15 1994
+@@ -1,3 +1,16 @@
++Sat Jun 19 14:00:00 1994 J"org Weule (weule@cs.uni-duesseldorf.de)
++
++        * version.c: version 1.11.2 (added --record-file)
++
++        * create.c: print header before incrementing the record #
++
++      * tar.c: inserted the option --record-file
++
++      * buffer.c: opens the record file
++
++      * list.c: writes the record information to rec_files instead of
++      msg_file
++
+ Thu Mar 25 13:32:40 1993  Michael I Bushnell  (mib@geech.gnu.ai.mit.edu)
+       * version.c: Released version 1.11.2.
+diff -ru tar-1.11.2/buffer.c tar-1.11.2.1/buffer.c
+--- tar-1.11.2/buffer.c        Fri Mar 19 21:05:11 1993
++++ tar-1.11.2.1/buffer.c      Thu Feb  9 23:01:33 1995
+@@ -62,6 +62,8 @@
+ /* Either stdout or stderr:  The thing we write messages (standard msgs, not
+    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
+ FILE *msg_file = stdout;
++FILE *rec_file = stdout;
++char *rec_file_name = NULL ;
+ #define       STDIN   0               /* Standard input  file descriptor */
+ #define       STDOUT  1               /* Standard output file descriptor */
+@@ -115,7 +117,7 @@
+ /*
+  * Record number of the start of this block of records
+  */
+-long baserec;
++long baserec = 0 ;
+ /*
+  * Error recovery stuff
+@@ -534,7 +536,44 @@
+ open_archive (reading)
+      int reading;
+ {
+-  msg_file = f_exstdout ? stderr : stdout;
++  time_t start_time = time(0);
++  rec_file = msg_file = f_exstdout ? stderr : stdout;
++  if ( rec_file_name != NULL )
++    {
++#define INSERT_TIMESTAMP
++#ifdef INSERT_TIMESTAMP
++      /*
++       * A record-file name with '%T' will be expanded with a decimal
++       * value for the timestamp of the archive. This is the time value
++       * stored in the label record.
++       * If you are using only one computer, this should be a unique number.
++       * You are able to create different rec-files for all your archives,
++       * as well as finding the index of your archive in a reliable way.
++       *
++       * Another way would be to let us set the timestamp by another option.
++       * tar --timestamp <ts-number> ...
++       */
++      char rfn[256];
++      if ( reading == 0 ) {
++        char*p= rec_file_name ;
++        int i = 0 ;
++        int n;
++        while ( p[0] != '\0' ) {
++          if ( p[0] == '%' && p[1] == 'T' ) {
++            i += sprintf(rfn+i,"%d",start_time), p += 2 ;
++          } else { rfn[i++] = *p++ ; }
++        }
++        rfn[i] = '\0' ;
++      } else strcpy(rfn,rec_file_name);
++#else
++      char*rfn=rec_file_name;
++#endif
++      if ( ( rec_file = fopen(rfn,"w")) == NULL )
++        {
++          fprintf(rec_file,"Cannot open %s.\n",rec_file_name);
++          exit(1);
++        }
++    }
+   if (blocksize == 0)
+     {
+@@ -542,6 +581,19 @@
+       exit (EX_ARGSBAD);
+     }
++  if ( ( f_sayblock ) && ( f_volhdr ) )
++    {
++      fprintf(rec_file,
++        "loc             timestamp is %d \n",
++        start_time);
++    }
++  if ( f_sayblock && (blocksize != 10240) )
++    {
++      fprintf(rec_file,
++        "loc             block length is %d bytes = %d * 512 bytes \n",
++        blocksize,blocksize>>9);
++    }
++
+   if (n_ar_files == 0)
+     {
+       msg ("No archive name given, what should I do?");
+@@ -648,6 +700,38 @@
+   setmode (archive, O_BINARY);
+ #endif
++#if defined(MTTELL)
++  /* Prints the file number of the archive */
++  if ( f_sayblock )
++    {
++      struct mtget get ;
++      int i ;
++      i = ioctl(archive,MTIOCGET,&get);
++      if (( i == 0 ) && ( get.mt_fileno >= 0 ))
++        {
++          fprintf(rec_file,
++            "loc             number of the file is %d \n",
++            get.mt_fileno );
++        }
++    }
++#endif
++
++#if defined(MTIOCPOS)
++  /* Prints the tape block number on every Linux SCSI-device */
++  if ( f_sayblock )
++    {
++      struct mtpos pos ;
++      int i ;
++      i = ioctl(archive,MTIOCPOS,&pos);
++      if ( i == 0 )
++        {
++          fprintf(rec_file,
++            "loc             number of the first block is %d\n",
++            pos.mt_blkno );
++        }
++    }
++#endif
++
+   if (reading)
+     {
+       ar_last = ar_block;     /* Set up for 1st block = # 0 */
+@@ -700,7 +784,7 @@
+       strcpy (ar_block->header.arch_name, f_volhdr);
+       current_file_name = ar_block->header.arch_name;
+       ar_block->header.linkflag = LF_VOLHDR;
+-      to_oct (time (0), 1 + 12, ar_block->header.mtime);
++      to_oct (start_time, 1 + 12, ar_block->header.mtime);
+       finish_header (ar_block);
+       /* ar_record++; */
+     }
+diff -ru tar-1.11.2/create.c tar-1.11.2.1/create.c
+--- tar-1.11.2/create.c        Thu Mar 25 19:32:31 1993
++++ tar-1.11.2.1/create.c      Mon Oct  3 21:06:01 1994
+@@ -1340,7 +1340,10 @@
+   to_oct ((long) sum, 8, header->header.chksum);
+   header->header.chksum[6] = '\0';    /* Zap the space */
+-  userec (header);
++  /* print header first to get the same output with 'tar -tvR'
++   * and 'tar -cvR'
++   */
++  /* userec (header); */
+   if (f_verbose)
+     {
+@@ -1353,6 +1356,8 @@
+       head_standard = f_standard;
+       print_header ();
+     }
++
++  userec (header);
+   return;
+ }
+diff -ru tar-1.11.2/list.c tar-1.11.2.1/list.c
+--- tar-1.11.2/list.c  Tue Mar 16 20:56:01 1993
++++ tar-1.11.2.1/list.c        Wed Oct 12 14:01:01 1994
+@@ -48,6 +48,7 @@
+ #include "port.h"
+ extern FILE *msg_file;
++extern FILE *rec_file;
+ long from_oct ();             /* Decode octal number */
+ void demode ();                       /* Print file mode */
+@@ -563,7 +564,7 @@
+   extern long baserec;
+   if (f_sayblock)
+-    fprintf (msg_file, "rec %10d: ", baserec + (ar_record - ar_block));
++    fprintf (rec_file, "rec %10d: ", baserec + (ar_record - ar_block));
+   /* annofile(msg_file, (char *)NULL); */
+   if (f_verbose <= 1)
+@@ -574,7 +575,7 @@
+       name = quote_copy_string (current_file_name);
+       if (name == 0)
+       name = current_file_name;
+-      fprintf (msg_file, "%s\n", name);
++      fprintf (rec_file, "%s\n", name);
+       if (name != current_file_name)
+       free (name);
+     }
+@@ -585,6 +586,11 @@
+       switch (head->header.linkflag)
+       {
+       case LF_VOLHDR:
++          /* dirty bug fix to display the header processing
++           * tar cvvf /dev/null --label 'hello world' blah...
++           * J"org Weule weule@cs.uni-duesseldorf.de
++           */
++          hstat.st_mtime = from_oct(1 + 12 , head->header.mtime);
+         modes[0] = 'V';
+         break;
+@@ -689,7 +695,7 @@
+       name = quote_copy_string (current_file_name);
+       if (!name)
+       name = current_file_name;
+-      fprintf (msg_file, "%s %s/%s %*s%s %s %s %s",
++      fprintf (rec_file, "%s %s/%s %*s%s %s %s %s",
+              modes,
+              user,
+              group,
+@@ -707,7 +713,7 @@
+         name = quote_copy_string (current_link_name);
+         if (!name)
+           name = current_link_name;
+-        fprintf (msg_file, " -> %s\n", name);
++        fprintf (rec_file, " -> %s\n", name);
+         if (name != current_link_name)
+           free (name);
+         break;
+@@ -716,13 +722,13 @@
+         name = quote_copy_string (current_link_name);
+         if (!name)
+           name = current_link_name;
+-        fprintf (msg_file, " link to %s\n", current_link_name);
++        fprintf (rec_file, " link to %s\n", current_link_name);
+         if (name != current_link_name)
+           free (name);
+         break;
+       default:
+-        fprintf (msg_file, " unknown file type '%c'\n",
++        fprintf (rec_file, " unknown file type '%c'\n",
+                  head->header.linkflag);
+         break;
+@@ -735,23 +741,23 @@
+       case LF_FIFO:
+       case LF_CONTIG:
+       case LF_DUMPDIR:
+-        putc ('\n', msg_file);
++        putc ('\n', rec_file);
+         break;
+       case LF_VOLHDR:
+-        fprintf (msg_file, "--Volume Header--\n");
++        fprintf (rec_file, "--Volume Header--\n");
+         break;
+       case LF_MULTIVOL:
+-        fprintf (msg_file, "--Continued at byte %ld--\n", from_oct (1 + 12, head->header.offset));
++        fprintf (rec_file, "--Continued at byte %ld--\n", from_oct (1 + 12, head->header.offset));
+         break;
+       case LF_NAMES:
+-        fprintf (msg_file, "--Mangled file names--\n");
++        fprintf (rec_file, "--Mangled file names--\n");
+         break;
+       }
+     }
+-  fflush (msg_file);
++  fflush (rec_file);
+ }
+ /*
+@@ -774,12 +780,12 @@
+       demode ((unsigned) mode, modes + 1);
+       if (f_sayblock)
+-      fprintf (msg_file, "rec %10d: ", baserec + (ar_record - ar_block));
++      fprintf (rec_file, "rec %10d: ", baserec + (ar_record - ar_block));
+       /* annofile(msg_file, (char *)NULL); */
+       name = quote_copy_string (pathname);
+       if (!name)
+       name = pathname;
+-      fprintf (msg_file, "%s %*s %.*s\n",
++      fprintf (rec_file, "%s %*s %.*s\n",
+              modes,
+              ugswidth + DATEWIDTH,
+              "Creating directory:",
+diff -ru tar-1.11.2/tar.c tar-1.11.2.1/tar.c
+--- tar-1.11.2/tar.c   Wed Mar 17 16:30:46 1993
++++ tar-1.11.2.1/tar.c Thu Oct 13 00:48:14 1994
+@@ -71,6 +71,8 @@
+ extern FILE *msg_file;
++extern FILE *rec_file;
++extern char *rec_file_name;
+ int check_exclude ();
+ void add_exclude ();
+@@ -122,6 +124,7 @@
+   {"null", 0, 0, 16},
+   {"directory", 1, 0, 'C'},
+   {"record-number", 0, &f_sayblock, 1},
++  {"record-file",1,0,19},
+   {"files-from", 1, 0, 'T'},
+   {"label", 1, 0, 'V'},
+   {"exclude-from", 1, 0, 'X'},
+@@ -361,6 +364,11 @@
+         f_compressprog = optarg;
+         break;
++      case 19:
++        rec_file_name = optarg ;
++        f_sayblock++;         /* Print block #s for debug */
++        break;
++
+       case 'g':               /* We are making a GNU dump; save
+                                  directories at the beginning of
+                                  the archive, and include in each
+@@ -731,6 +739,7 @@
+ ", stdout);                   /* KLUDGE */
+   fputs ("\
+ -R, --record-number   show record number within archive with each message\n\
++--record-file           print the record information to file, enable -R\n\
+ --remove-files                remove files after adding them to the archive\n\
+ -s, --same-order,\n\
+     --preserve-order  list of names to extract is sorted to match archive\n\
+diff -ru tar-1.11.2/version.c tar-1.11.2.1/version.c
+--- tar-1.11.2/version.c       Thu Mar 25 19:35:25 1993
++++ tar-1.11.2.1/version.c     Mon Oct  3 16:01:59 1994
+@@ -1 +1 @@
+-char version_string[] = "GNU tar version 1.11.2";
++char version_string[] = "GNU tar version 1.11.2 (added --record-file)";
diff --git a/tar-1.11.8.patch b/tar-1.11.8.patch
new file mode 100644 (file)
index 0000000..462e852
--- /dev/null
@@ -0,0 +1,513 @@
+diff -ru tar-1.11.8/lib/rx.h tar-1.11.8.1/lib/rx.h
+--- tar-1.11.8/lib/rx.h        Fri May  5 14:17:10 1995
++++ tar-1.11.8.1/lib/rx.h      Fri May  5 14:17:10 1995
+@@ -1382,7 +1382,7 @@
+ /* If this bit is set, then `{...}' defines an interval, and \{ and \}
+      are literals.
+-  If not smt, then `\{...\}' defines an interval.  */
++  If not set, then `\{...\}' defines an interval.  */
+ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+ /* If this bit is set, (...) defines a group, and \( and \) are literals.
+diff -ru tar-1.11.8/src/buffer.c tar-1.11.8.1/src/buffer.c
+--- tar-1.11.8/src/buffer.c    Mon May 29 02:26:27 1995
++++ tar-1.11.8.1/src/buffer.c  Mon Feb  5 20:20:19 1996
+@@ -46,6 +46,7 @@
+ /* Where we write messages (standard messages, not errors) to.  Stdout
+    unless we're writing a pipe, in which case stderr.  */
+ FILE *stdlis;
++FILE *stdrec;
+ #define       STDIN   0               /* standard input  file descriptor */
+ #define       STDOUT  1               /* standard output file descriptor */
+@@ -77,7 +78,7 @@
+ static int childpid = 0;
+ /* Record number of the start of this block of records  */
+-long baserec;
++long baserec = 0 ;
+ /* Error recovery stuff  */
+ static int r_error_count;
+@@ -520,11 +521,64 @@
+ void
+ open_archive (int reading)
+ {
+-  stdlis = flag_exstdout ? stderr : stdout;
++  time_t start_time = time(0) ;
++  stdrec = stdlis = flag_exstdout ? stderr : stdout;
++  if ( record_file_name != NULL )
++    {
++#define INSERT_TIMESTAMP
++#ifdef INSERT_TIMESTAMP
++      /*
++       * A record-file name with '%T' will be expanded with a decimal
++       * value for the timestamp of the archive. This is the time value
++       * stored in the label record.
++       * If you are using only one computer, this should be a unique number.
++       * You are able to create different rec-files for all your archives,
++       * as well as finding the index of your archive in a reliable way.
++       *
++       * Another way would be to let us set the timestamp by another option.
++       * tar --timestamp <ts-number> ...
++       */
++      char rfn[256];
++      if ( reading == 0 ) {
++        char*p= record_file_name ;
++        int i = 0 ;
++        int n;
++        while ( p[0] != '\0' ) {
++          if ( p[0] == '%' && p[1] == 'T' ) {
++            /* i += */ sprintf(rfn+i,"%d",start_time);
++            i = strlen(rfn) ;
++            p += 2 ;
++          } else { rfn[i++] = *p++ ; }
++        }
++        rfn[i] = '\0' ;
++      } else strcpy(rfn,record_file_name);
++#else
++      char*rfn=record_file_name;
++#endif
++      if ( ( stdrec = fopen(rfn,"w")) == NULL )
++        {
++          fprintf(stdlis,"Cannot open %s.\n",record_file_name);
++          exit(1);
++        }
++    }
++
+   if (blocksize == 0)
+     ERROR ((TAREXIT_FAILURE, 0, _("Invalid value for blocksize")));
++  if ( ( flag_sayblock ) && ( flag_volhdr ) )
++    {
++      fprintf(stdrec,
++        "loc             timestamp is %d \n",
++        start_time);
++    }
++  if ( flag_sayblock && (blocksize != 10240) )
++    {
++      fprintf(stdrec,
++        "loc             block length is %d bytes = %d * 512 bytes \n",
++        blocksize,blocksize>>9);
++    }
++
+   if (archive_names == 0)
+     ERROR ((TAREXIT_FAILURE, 0,
+           _("No archive name given, what should I do?")));
+@@ -618,6 +672,38 @@
+   setmode (archive, O_BINARY);
+ #endif
++#if defined(MTIOCGET)
++  /* Prints the file number of the archive */
++  if ( flag_sayblock )
++    {
++      struct mtget get ;
++      int i ;
++      i = ioctl(archive,MTIOCGET,&get);
++      if (( i == 0 ) && ( get.mt_fileno >= 0 ))
++        {
++          fprintf(stdrec,
++            "loc             number of the file is %d \n",
++            get.mt_fileno );
++        }
++    }
++#endif
++
++#if defined(MTIOCPOS)
++  /* Prints the tape block number on every Linux SCSI-device */
++  if ( flag_sayblock )
++    {
++      struct mtpos pos ;
++      int i ;
++      i = ioctl(archive,MTIOCPOS,&pos);
++      if ( i == 0 )
++        {
++          fprintf(stdrec,
++            "loc             number of the first block is %d\n",
++            pos.mt_blkno );
++        }
++    }
++#endif
++
+   if (reading)
+     {
+       ar_last = ar_block;     /* set up for 1st block = # 0 */
+@@ -666,7 +752,7 @@
+       assign_string (&current_file_name, ar_block->header.arch_name);
+       ar_block->header.linkflag = LF_VOLHDR;
+-      to_oct (time (0), 1 + 12, ar_block->header.mtime);
++      to_oct (start_time , 1 + 12, ar_block->header.mtime);
+       finish_header (ar_block);
+ #if 0
+       ar_record++;
+@@ -727,7 +813,7 @@
+   if (err != blocksize && !flag_multivol)
+     writeerror (err);
+   else if (flag_totals)
+-    tot_written += blocksize;
++    tot_written += blocking;
+   if (err > 0)
+     bytes_written += err;
+@@ -816,7 +902,7 @@
+   if (err != blocksize)
+     writeerror (err);
+   else if (flag_totals)
+-    tot_written += blocksize;
++    tot_written += blocking;
+   bytes_written = blocksize;
+diff -ru tar-1.11.8/src/create.c tar-1.11.8.1/src/create.c
+--- tar-1.11.8/src/create.c    Sat Jun 17 23:08:13 1995
++++ tar-1.11.8.1/src/create.c  Sun Dec  1 01:55:08 1996
+@@ -315,7 +315,10 @@
+   to_oct ((long) sum, 8, header->header.chksum);
+   header->header.chksum[6] = '\0';    /* zap the space */
+-  userec (header);
++  /* print header first to get the same output with 'tar -tvR'
++   * and 'tar -cvR'
++   */
++  /* userec (header); */
+   if (flag_verbose)
+     {
+@@ -327,6 +330,8 @@
+       head_standard = flag_standard;
+       print_header ();
+     }
++
++  userec (header) ;
+   return;
+ }
+diff -ru tar-1.11.8/src/extract.c tar-1.11.8.1/src/extract.c
+--- tar-1.11.8/src/extract.c   Sun Jun 11 15:40:21 1995
++++ tar-1.11.8.1/src/extract.c Sun Dec  1 01:55:28 1996
+@@ -684,6 +684,7 @@
+     case LF_LONGNAME:
+     case LF_LONGLINK:
+       ERROR ((0, 0, _("Visible long name error")));
++      print_header();
+       skip_file ((long) hstat.st_size);
+       break;
+     }
+diff -ru tar-1.11.8/src/list.c tar-1.11.8.1/src/list.c
+--- tar-1.11.8/src/list.c      Wed May  3 05:28:17 1995
++++ tar-1.11.8.1/src/list.c    Sun Dec  1 16:22:12 1996
+@@ -200,7 +200,7 @@
+         if (written > size)
+           written = size;
+         errno = 0;
+-        check = fwrite (data, sizeof (char), written, stdlis);
++        check = fwrite (data, sizeof (char), written, stdrec);
+         userec ((union record *) (data + written - 1));
+         if (check != written)
+           {
+@@ -213,8 +213,8 @@
+       if (flag_multivol)
+       assign_string (&save_name, NULL);
+       saverec (NULL);         /* unsave it */
+-      fputc ('\n', stdlis);
+-      fflush (stdlis);
++      fputc ('\n', stdrec);
++      fflush (stdrec);
+       return;
+     }
+@@ -353,6 +353,8 @@
+         longp = ((header->header.linkflag == LF_LONGNAME)
+                  ? &next_long_name
+                  : &next_long_link);
++        assign_string (&current_file_name, header->header.arch_name);
++          print_header();
+         userec (header);
+         if (*longp)
+@@ -533,9 +535,9 @@
+   char *name;
+   if (flag_sayblock)
+-    fprintf (stdlis, _("rec %10ld: "), baserec + (ar_record - ar_block));
++    fprintf (stdrec, _("rec %10ld: "), baserec + (ar_record - ar_block));
+ #if 0
+-  annofile (stdlis, (char *) NULL);
++  annofile (stdrec, (char *) NULL);
+ #endif
+   if (flag_verbose <= 1)
+@@ -547,11 +549,11 @@
+       if (quoted_name)
+       {
+-        fprintf (stdlis, "%s\n", quoted_name);
++        fprintf (stdrec, "%s\n", quoted_name);
+         free (quoted_name);
+       }
+       else
+-      fprintf (stdlis, "%s\n", current_file_name);
++      fprintf (stdrec, "%s\n", current_file_name);
+     }
+   else
+     {
+@@ -562,6 +564,11 @@
+       switch (head->header.linkflag)
+       {
+       case LF_VOLHDR:
++          /* dirty bug fix to display the header processing
++           * tar cvvf /dev/null --label 'hello world' blah...
++           * J"org Weule weule@cs.uni-duesseldorf.de
++           */
++          hstat.st_mtime = from_oct(1 + 12 , head->header.mtime);
+         modes[0] = 'V';
+         break;
+@@ -574,8 +581,13 @@
+         break;
+       case LF_LONGNAME:
++        /*ERROR ((0, 0, _("Visible longname error")));*/
++        modes[0] = 'L';
++        break;
++
+       case LF_LONGLINK:
+-        ERROR ((0, 0, _("Visible longname error")));
++        /*ERROR ((0, 0, _("Visible longname error")));*/
++        modes[0] = 'K';
+         break;
+       case LF_SPARSE:
+@@ -663,18 +675,18 @@
+       if (pad > ugswidth)
+       ugswidth = pad;
+-      fprintf (stdlis, "%s %s/%s %*s%s %s %s",
++      fprintf (stdrec, "%s %s/%s %*s%s %s %s",
+              modes, user, group, ugswidth - pad, "",
+              size, timestamp + 4, timestamp + 20);
+       name = quote_copy_string (current_file_name);
+       if (name)
+       {
+-        fprintf (stdlis, " %s", name);
++        fprintf (stdrec, " %s", name);
+         free (name);
+       }
+       else
+-      fprintf (stdlis, " %s", current_file_name);
++      fprintf (stdrec, " %s", current_file_name);
+       switch (head->header.linkflag)
+       {
+@@ -682,26 +694,26 @@
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, " -> %s\n", name);
++            fprintf (stdrec, " -> %s\n", name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, " -> %s\n", current_link_name);
++          fprintf (stdrec, " -> %s\n", current_link_name);
+         break;
+       case LF_LINK:
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, _(" link to %s\n"), name);
++            fprintf (stdrec, _(" link to %s\n"), name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, _(" link to %s\n"), current_link_name);
++          fprintf (stdrec, _(" link to %s\n"), current_link_name);
+         break;
+       default:
+-        fprintf (stdlis, _(" unknown file type `%c'\n"),
++        fprintf (stdrec, _(" unknown file type `%c'\n"),
+                  head->header.linkflag);
+         break;
+@@ -714,24 +726,32 @@
+       case LF_FIFO:
+       case LF_CONTIG:
+       case LF_DUMPDIR:
+-        putc ('\n', stdlis);
++        putc ('\n', stdrec);
++        break;
++
++      case LF_LONGNAME:
++        fprintf (stdrec, _("--Long Name--\n"));
++        break;
++
++      case LF_LONGLINK:
++        fprintf (stdrec, _("--Long Link--\n"));
+         break;
+       case LF_VOLHDR:
+-        fprintf (stdlis, _("--Volume Header--\n"));
++        fprintf (stdrec, _("--Volume Header--\n"));
+         break;
+       case LF_MULTIVOL:
+-        fprintf (stdlis, _("--Continued at byte %ld--\n"),
++        fprintf (stdrec, _("--Continued at byte %ld--\n"),
+                  from_oct (1 + 12, head->header.offset));
+         break;
+       case LF_NAMES:
+-        fprintf (stdlis, _("--Mangled file names--\n"));
++        fprintf (stdrec, _("--Mangled file names--\n"));
+         break;
+       }
+     }
+-  fflush (stdlis);
++  fflush (stdrec);
+ }
+ /*--------------------------------------------------------------.
+@@ -753,9 +773,9 @@
+       demode ((unsigned) mode, modes + 1);
+       if (flag_sayblock)
+-      fprintf (stdlis, _("rec %10ld: "), baserec + (ar_record - ar_block));
++      fprintf (stdrec, _("rec %10ld: "), baserec + (ar_record - ar_block));
+ #if 0
+-      annofile (stdlis, (char *) NULL);
++      annofile (stdrec, (char *) NULL);
+ #endif
+       name = quote_copy_string (pathname);
+       if (!name)
+diff -ru tar-1.11.8/src/tar.c tar-1.11.8.1/src/tar.c
+--- tar-1.11.8/src/tar.c       Sat Jun 17 22:48:32 1995
++++ tar-1.11.8.1/src/tar.c     Mon Apr  8 16:54:08 1996
+@@ -860,6 +860,7 @@
+ #define OPTION_VOLNO_FILE     15
+ #define OPTION_COMPRESS_PROG  16
+ #define OPTION_RSH_COMMAND    17
++#define OPTION_RECORD_FILE      18
+ /* Some cleanup is made in GNU tar long options.  Using old names will send
+    a warning to stderr.  */
+@@ -925,6 +926,7 @@
+   {"preserve-permissions", no_argument, NULL, 'p'},
+   {"read-full-blocks", no_argument, NULL, 'B'},
+   {"record-number", no_argument, NULL, 'R'},
++  {"record-file", required_argument, NULL, OPTION_RECORD_FILE},
+   {"remove-files", no_argument, &flag_remove_files, 1},
+   {"rsh-command", required_argument, NULL, OPTION_RSH_COMMAND},
+   {"same-order", no_argument, NULL, 's'},
+@@ -1059,6 +1061,7 @@
+       --checkpoint      print directory names while reading the archive\n\
+       --totals          print total bytes written while creating archive\n\
+   -R, --record-number   show record number within archive with each message\n\
++      --record-file     print the record information to file, enable -R\n\
+   -w, --interactive     ask for confirmation for every action\n\
+       --confirmation    same as -w\n"),
+            stdout);
+@@ -1212,6 +1215,11 @@
+       flag_rsh_command = optarg;
+       break;
++      case OPTION_RECORD_FILE:
++        record_file_name = optarg ;
++        flag_sayblock++;         /* Print block #s for debug */
++        break;
++
+       case 'g':
+       /* We are making a GNU dump; save directories at the beginning
+          of the archive, and include in each directory its contents.  */
+@@ -1626,9 +1634,42 @@
+       break;
+     case COMMAND_CREATE:
++/*
++ * Comment the next line out if you have problems. Joerg Weule
++ */
++#define PRINT_TROUPUT
++#ifdef PRINT_TROUPUT
++      start_time = time(0);
++      create_archive ();
++      if (flag_totals) {
++      time_t end_time = time(0);
++      double sec = end_time - start_time ;
++      double t = ((double)tot_written) * RECORDSIZE ;
++      fprintf (stderr, _("Total bytes written: %.0f"),t);
++      if ( t >= 1e9 ) fprintf(stderr, _(" (%3.1f Gb)"),t/1e9 ); else
++      if ( t >= 1e6 ) fprintf(stderr, _(" (%3.1f Mb)"),t/1e6 ); else
++      if ( t >= 1024 ) fprintf(stderr, _(" (%3.1f Kb)"),t/1024 );
++      fprintf(stderr,"\n");
++      if ( sec > 0.1 ){
++        long s, m, h = sec ;
++          m = h ;
++        h /= 3600 ;
++          m -= h * 3600 ;
++          s = m ;
++          m /= 60 ;
++          s -= m / 60 ;
++        fprintf (stderr, _("Elapsed time: %02d:%02d:%02d, %g sec\n"), h,m,s,sec);
++        if ( !flag_multivol)
++          fprintf (stderr, _("Throughput per second: %.0fKb/sec\n"),
++            t/sec/1024);
++      }
++      }
++#else
+       create_archive ();
+       if (flag_totals)
+-      fprintf (stderr, _("Total bytes written: %d\n"), tot_written);
++      fprintf (stderr, _("Total bytes written: %g\n")),
++          ((double)tot_written) * RECORDSIZE );
++#endif
+       break;
+     case COMMAND_EXTRACT:
+diff -ru tar-1.11.8/src/tar.h tar-1.11.8.1/src/tar.h
+--- tar-1.11.8/src/tar.h       Sat Jun 17 20:36:49 1995
++++ tar-1.11.8.1/src/tar.h     Mon Feb  5 20:19:19 1996
+@@ -183,6 +183,9 @@
+     int numbytes;
+   };
++/* Time of writing.  */
++GLOBAL time_t start_time;
++
+ /* Start of block of archive.  */
+ GLOBAL union record *ar_block;
+@@ -207,6 +210,9 @@
+ /* File containing names to work on.  */
+ GLOBAL const char *namefile_name;
++/* File to write record information to. */
++GLOBAL char *record_file_name;
++
+ /* \n or \0.  */
+ GLOBAL char filename_terminator;
+@@ -219,8 +225,8 @@
+ /* Initial size of the sparsearray.  */
+ GLOBAL int sp_array_size;
+-/* Total written to output.  */
+-GLOBAL int tot_written;
++/* Total written to output in records.  */
++GLOBAL long int tot_written;
+ /* Compiled regex for extract label.  */
+ GLOBAL struct re_pattern_buffer *label_pattern;
+@@ -338,6 +344,7 @@
+ extern long baserec;
+ extern FILE *stdlis;
++extern FILE *stdrec;
+ extern char *save_name;
+ extern long save_sizeleft;
+ extern long save_totsize;
diff --git a/tar-1.12.patch b/tar-1.12.patch
new file mode 100644 (file)
index 0000000..7d1eec7
--- /dev/null
@@ -0,0 +1,487 @@
+diff -ru tar-1.12/src/buffer.c tar-1.12.1/src/buffer.c
+--- tar-1.12/src/buffer.c      Fri Apr 25 15:48:46 1997
++++ tar-1.12.1/src/buffer.c    Fri Jul  3 12:46:24 1998
+@@ -55,6 +55,7 @@
+ static tarlong total_written; /* bytes written on all volumes */
+ static tarlong bytes_written; /* bytes written on this volume */
++static time_t start_time ;
+ /* FIXME: The following four variables should ideally be static to this
+    module.  However, this cannot be done yet, as update.c uses the first
+@@ -71,6 +72,7 @@
+ /* Where we write list messages (not errors, not interactions) to.  Stdout
+    unless we're writing a pipe, in which case stderr.  */
+ FILE *stdlis;
++FILE *stdrec;
+ static void backspace_output PARAMS ((void));
+ static int new_volume PARAMS ((enum access_mode));
+@@ -160,6 +162,36 @@
+   fprintf (stderr, _("Total bytes written: "));
+   print_tarlong (total_written, stderr);
+   fprintf (stderr, "\n");
++#define PRINT_TROUPUT
++#ifdef PRINT_TROUPUT
++/*
++ * Comment the next line out if you have problems. Joerg Weule
++ */
++  {
++       time_t end_time = time(0);
++       double sec = end_time - start_time ;
++       double t = ((double)total_written) ;
++       fprintf (stderr, _("Total bytes written: %.0f"),t);
++       if ( t >= 1e9 ) fprintf(stderr, _(" (%3.1f Gb)"),t/1e9 ); else
++       if ( t >= 1e6 ) fprintf(stderr, _(" (%3.1f Mb)"),t/1e6 ); else
++       if ( t >= 1024 ) fprintf(stderr, _(" (%3.1f Kb)"),t/1024 );
++       fprintf(stderr,"\n");
++       if ( sec > 0.1 ){
++         long s, m, h = sec ;
++          m = h ;
++         h /= 3600 ;
++          m -= h * 3600 ;
++          s = m ;
++          m /= 60 ;
++          s -= m / 60 ;
++         fprintf (stderr, _("Elapsed time: %02d:%02d:%02d, %g sec\n"), h,m,s,sec);
++         if ( NULL == volume_label_option )
++           fprintf (stderr, _("Throughput per second: %.0fKb/sec\n"),
++             t/sec/1024);
++       }
++  }
++#endif
++
+ }
+ /*--------------------------------------------------------.
+@@ -669,6 +701,7 @@
+ {
+   int backed_up_flag = 0;
++  start_time = time(0) ;
+   stdlis = to_stdout_option ? stderr : stdout;
+   if (record_size == 0)
+@@ -823,6 +856,101 @@
+   setmode (archive, O_BINARY);
+ #endif
++  stdrec = stdlis ;
++  if ( record_file_name != NULL )
++    {
++#define INSERT_TIMESTAMP
++#ifdef INSERT_TIMESTAMP
++      /*
++       * A record-file name with '%T' will be expanded with a decimal
++       * value for the timestamp of the archive. This is the time value
++       * stored in the label record.
++       * If you are using only one computer, this should be a unique number.
++       * You are able to create different rec-files for all your archives,
++       * as well as finding the index of your archive in a reliable way.
++       *
++       * Another way would be to let us set the timestamp by another option.
++       * tar --timestamp <ts-number> ...
++       */
++      char rfn[256];
++      if ( subcommand_option == CREATE_SUBCOMMAND ) {
++        char*p= record_file_name ;
++        int i = 0 ;
++        int n;
++        while ( p[0] != '\0' ) {
++          if ( p[0] == '%' && p[1] == 'T' ) {
++            /* i += */ sprintf(rfn+i,"%d",start_time);
++            i = strlen(rfn) ;
++            p += 2 ;
++          } else { rfn[i++] = *p++ ; }
++        }
++        rfn[i] = '\0' ;
++      } else strcpy(rfn,record_file_name);
++#else
++      char*rfn=record_file_name;
++#endif
++      if ( ( stdrec = fopen(rfn,"w")) == NULL )
++        {
++          fprintf(stdlis,"Cannot open %s.\n",record_file_name);
++          exit(1);
++        }
++    }
++
++  if ( ( record_file_name ) && ( volume_label_option ) )
++    {
++      fprintf(stdrec,
++        "loc             timestamp is %d \n",
++        start_time);
++    }
++  if ( record_file_name && (record_size != 10240) )
++    {
++      fprintf(stdrec,
++        "loc             block length is %d bytes = %d * 512 bytes \n",
++        record_size,record_size>>9);
++    }
++
++
++#if defined(MTIOCGET)
++  /* Prints the file number of the archive */
++  if ( record_file_name )
++    {
++      struct mtget get ;
++      int i ;
++      i = ioctl(archive,MTIOCGET,&get);
++      if (( i == 0 ) && ( get.mt_fileno >= 0 ))
++        {
++          fprintf(stdrec,
++            "loc             number of the file is %d \n",
++            get.mt_fileno );
++        }
++    }
++#endif
++
++#if defined(MTIOCPOS)
++  /* Prints the tape block number on every Linux SCSI-device */
++  if ( record_file_name )
++    {
++      struct mtpos pos ;
++      int i ;
++      i = ioctl(archive,MTIOCPOS,&pos);
++      if ( i == 0 )
++        {
++          fprintf(stdrec,
++            "loc             number of the first block is %d\n",
++            pos.mt_blkno );
++        }
++    }
++#endif
++  if ( record_file_name )
++    {
++      char *d = malloc(PATH_MAX);
++      if( d && getcwd(d,PATH_MAX) )
++        fprintf(stdrec,
++            "loc             current directory is %s\n",
++            d);
++    }
++
++
+   switch (access)
+     {
+     case ACCESS_READ:
+@@ -856,7 +984,7 @@
+         assign_string (&current_file_name, record_start->header.name);
+         record_start->header.typeflag = GNUTYPE_VOLHDR;
+-        to_oct (time (0), 1 + 12, record_start->header.mtime);
++        to_oct (start_time, 1 + 12, record_start->header.mtime);
+         finish_header (record_start);
+ #if 0
+         current_block++;
+@@ -958,6 +1086,7 @@
+       memset ((void *) record_start, 0, BLOCKSIZE);
+       sprintf (record_start->header.name, "%s Volume %d", volume_label_option, volno);
+       to_oct (time (0), 1 + 12, record_start->header.mtime);
++      to_oct (start_time, 1 + 12, record_start->header.mtime);
+       record_start->header.typeflag = GNUTYPE_VOLHDR;
+       finish_header (record_start);
+     }
+diff -ru tar-1.12/src/common.h tar-1.12.1/src/common.h
+--- tar-1.12/src/common.h      Tue Apr 22 08:31:03 1997
++++ tar-1.12.1/src/common.h    Thu Jan 29 01:36:57 1998
+@@ -93,6 +93,9 @@
+ /* Name of this program.  */
+ GLOBAL const char *program_name;
++/* Time of writing.  */
++GLOBAL time_t start_time;
++
+ /* Main command option.  */
+ enum subcommand
+@@ -141,6 +144,9 @@
+ /* Boolean value.  */
+ GLOBAL int block_number_option;
++/* Name of the index file */
++GLOBAL char *record_file_name;
++
+ /* Boolean value.  */
+ GLOBAL int checkpoint_option;
+@@ -335,6 +341,7 @@
+ /* Module buffer.c.  */
+ extern FILE *stdlis;
++extern FILE *stdrec;
+ extern char *save_name;
+ extern long save_sizeleft;
+ extern long save_totsize;
+diff -ru tar-1.12/src/create.c tar-1.12.1/src/create.c
+--- tar-1.12/src/create.c      Fri Apr 25 15:48:48 1997
++++ tar-1.12.1/src/create.c    Thu Jan 29 01:00:13 1998
+@@ -329,7 +329,6 @@
+   to_oct ((long) sum, 8, header->header.chksum);
+   header->header.chksum[6] = '\0';    /* zap the space */
+-  set_next_block_after (header);
+   if (verbose_option
+       && header->header.typeflag != GNUTYPE_LONGLINK
+@@ -342,6 +341,8 @@
+       current_format = archive_format;
+       print_header ();
+     }
++
++  set_next_block_after (header);
+ }
\f
+ /* Sparse file processing.  */
+diff -ru tar-1.12/src/list.c tar-1.12.1/src/list.c
+--- tar-1.12/src/list.c        Fri Apr 25 22:16:30 1997
++++ tar-1.12.1/src/list.c      Thu Jan 29 11:57:27 1998
+@@ -120,7 +120,7 @@
+       case HEADER_ZERO_BLOCK:
+         if (block_number_option)
+-          fprintf (stdlis, _("block %10ld: ** Block of NULs **\n"),
++          fprintf (stdrec, _("block %10ld: ** Block of NULs **\n"),
+                    current_block_ordinal ());
+         set_next_block_after (current_header);
+@@ -131,7 +131,7 @@
+       case HEADER_END_OF_FILE:
+         if (block_number_option)
+-          fprintf (stdlis, _("block %10ld: ** End of File **\n"),
++          fprintf (stdrec, _("block %10ld: ** End of File **\n"),
+                    current_block_ordinal ());
+         break;
+@@ -208,7 +208,7 @@
+         if (written > size)
+           written = size;
+         errno = 0;            /* FIXME: errno should be read-only */
+-        check = fwrite (data_block->buffer, sizeof (char), written, stdlis);
++        check = fwrite (data_block->buffer, sizeof (char), written, stdrec);
+         set_next_block_after ((union block *)
+                               (data_block->buffer + written - 1));
+         if (check != written)
+@@ -221,8 +221,8 @@
+       }
+       if (multi_volume_option)
+       assign_string (&save_name, NULL);
+-      fputc ('\n', stdlis);
+-      fflush (stdlis);
++      fputc ('\n', stdrec);
++      fflush (stdrec);
+       return;
+     }
+@@ -367,6 +367,9 @@
+                  ? &next_long_name
+                  : &next_long_link);
++          assign_string (&current_file_name, header->header.name);
++          print_header();
++
+         set_next_block_after (header);
+         if (*longp)
+           free (*longp);
+@@ -614,7 +617,7 @@
+   char *name;
+   if (block_number_option)
+-    fprintf (stdlis, _("block %10ld: "), current_block_ordinal ());
++    fprintf (stdrec, _("block %10ld: "), current_block_ordinal ());
+   if (verbose_option <= 1)
+     {
+@@ -624,11 +627,11 @@
+       if (quoted_name)
+       {
+-        fprintf (stdlis, "%s\n", quoted_name);
++        fprintf (stdrec, "%s\n", quoted_name);
+         free (quoted_name);
+       }
+       else
+-      fprintf (stdlis, "%s\n", current_file_name);
++      fprintf (stdrec, "%s\n", current_file_name);
+     }
+   else
+     {
+@@ -650,8 +653,12 @@
+         break;
+       case GNUTYPE_LONGNAME:
++        modes[0] = 'L';
++        break;
++
+       case GNUTYPE_LONGLINK:
+-        ERROR ((0, 0, _("Visible longname error")));
++        /*ERROR ((0, 0, _("Visible longname error")));*/
++        modes[0] = 'K';
+         break;
+       case GNUTYPE_SPARSE:
+@@ -743,22 +750,22 @@
+       ugswidth = pad;
+ #if USE_OLD_CTIME
+-      fprintf (stdlis, "%s %s/%s %*s%s %s %s",
++      fprintf (stdrec, "%s %s/%s %*s%s %s %s",
+              modes, user, group, ugswidth - pad, "",
+              size, timestamp + 4, timestamp + 20);
+ #else
+-      fprintf (stdlis, "%s %s/%s %*s%s %s",
++      fprintf (stdrec, "%s %s/%s %*s%s %s",
+              modes, user, group, ugswidth - pad, "", size, timestamp);
+ #endif
+       name = quote_copy_string (current_file_name);
+       if (name)
+       {
+-        fprintf (stdlis, " %s", name);
++        fprintf (stdrec, " %s", name);
+         free (name);
+       }
+       else
+-      fprintf (stdlis, " %s", current_file_name);
++      fprintf (stdrec, " %s", current_file_name);
+       switch (current_header->header.typeflag)
+       {
+@@ -766,26 +773,26 @@
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, " -> %s\n", name);
++            fprintf (stdrec, " -> %s\n", name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, " -> %s\n", current_link_name);
++          fprintf (stdrec, " -> %s\n", current_link_name);
+         break;
+       case LNKTYPE:
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, _(" link to %s\n"), name);
++            fprintf (stdrec, _(" link to %s\n"), name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, _(" link to %s\n"), current_link_name);
++          fprintf (stdrec, _(" link to %s\n"), current_link_name);
+         break;
+       default:
+-        fprintf (stdlis, _(" unknown file type `%c'\n"),
++        fprintf (stdrec, _(" unknown file type `%c'\n"),
+                  current_header->header.typeflag);
+         break;
+@@ -798,24 +805,24 @@
+       case FIFOTYPE:
+       case CONTTYPE:
+       case GNUTYPE_DUMPDIR:
+-        putc ('\n', stdlis);
++        putc ('\n', stdrec);
+         break;
+       case GNUTYPE_VOLHDR:
+-        fprintf (stdlis, _("--Volume Header--\n"));
++        fprintf (stdrec, _("--Volume Header--\n"));
+         break;
+       case GNUTYPE_MULTIVOL:
+-        fprintf (stdlis, _("--Continued at byte %ld--\n"),
++        fprintf (stdrec, _("--Continued at byte %ld--\n"),
+                  from_oct (1 + 12, current_header->oldgnu_header.offset));
+         break;
+       case GNUTYPE_NAMES:
+-        fprintf (stdlis, _("--Mangled file names--\n"));
++        fprintf (stdrec, _("--Mangled file names--\n"));
+         break;
+       }
+     }
+-  fflush (stdlis);
++  fflush (stdrec);
+ }
+ /*--------------------------------------------------------------.
+@@ -836,16 +843,16 @@
+       decode_mode ((unsigned) mode, modes + 1);
+       if (block_number_option)
+-      fprintf (stdlis, _("block %10ld: "), current_block_ordinal ());
++      fprintf (stdrec, _("block %10ld: "), current_block_ordinal ());
+       name = quote_copy_string (pathname);
+       if (name)
+       {
+-        fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
++        fprintf (stdrec, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
+                  _("Creating directory:"), length, name);
+         free (name);
+       }
+       else
+-      fprintf (stdlis, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
++      fprintf (stdrec, "%s %*s %.*s\n", modes, ugswidth + DATEWIDTH,
+                _("Creating directory:"), length, pathname);
+     }
+ }
+diff -ru tar-1.12/src/names.c tar-1.12.1/src/names.c
+--- tar-1.12/src/names.c       Tue Apr 22 07:35:50 1997
++++ tar-1.12.1/src/names.c     Fri Jul  3 12:46:24 1998
+@@ -332,6 +332,14 @@
+           FATAL_ERROR ((0, errno, _("Cannot change to directory %s"),
+                         name_buffer));
+         chdir_flag = 0;
++          if ( record_file_name )
++            {
++              char *d = malloc(PATH_MAX);
++              if( d && getcwd(d,PATH_MAX) )
++                fprintf(stdrec,
++                    "loc             current directory is %s\n",
++                    d);
++            }
+       }
+       else if (change_dirs && strcmp (name_buffer, "-C") == 0)
+       chdir_flag = 1;
+diff -ru tar-1.12/src/tar.c tar-1.12.1/src/tar.c
+--- tar-1.12/src/tar.c Fri Apr 25 22:09:49 1997
++++ tar-1.12.1/src/tar.c       Tue Jul 28 15:44:57 1998
+@@ -163,6 +163,7 @@
+ #define SUFFIX_OPTION                 15
+ #define USE_COMPRESS_PROGRAM_OPTION   16
+ #define VOLNO_FILE_OPTION             17
++#define OPTION_RECORD_FILE              18
+ /* Some cleanup is being made in GNU tar long options.  Using old names is
+    allowed for a while, but will also send a warning to stderr.  Take old
+@@ -251,6 +252,7 @@
+   {"read-full-records", no_argument, NULL, 'B'},
+   /* FIXME: --partial-blocks might be a synonym for --read-full-records?  */
+   {"record-number", no_argument, NULL, OBSOLETE_BLOCK_NUMBER},
++  {"record-file", required_argument, NULL, OPTION_RECORD_FILE},
+   {"record-size", required_argument, NULL, RECORD_SIZE_OPTION},
+   {"remove-files", no_argument, &remove_files_option, 1},
+   {"rsh-command", required_argument, NULL, RSH_COMMAND_OPTION},
+@@ -410,6 +412,7 @@
+       --checkpoint      print directory names while reading the archive\n\
+       --totals          print total bytes written while creating archive\n\
+   -R, --block-number    show block number within archive with each message\n\
++      --record-file      print the record information to file, enable -R\n\
+   -w, --interactive     ask for confirmation for every action\n\
+       --confirmation    same as -w\n"),
+            stdout);
+@@ -754,6 +757,10 @@
+       block_number_option = 1;
+       break;
++
++      case OPTION_RECORD_FILE:
++        record_file_name = optarg ;
++        break;
+       case 's':
+       /* Names to extr are sorted.  */
diff --git a/tar-1.13.patch b/tar-1.13.patch
new file mode 100644 (file)
index 0000000..d97879e
--- /dev/null
@@ -0,0 +1,540 @@
+diff -ru tar-1.13/src/buffer.c tar-1.13.1/src/buffer.c
+--- tar-1.13/src/buffer.c      Mon Jul  5 08:47:59 1999
++++ tar-1.13.1/src/buffer.c    Sun Aug  6 23:37:01 2000
+@@ -68,6 +68,7 @@
+ /* Where we write list messages (not errors, not interactions) to.  Stdout
+    unless we're writing a pipe, in which case stderr.  */
+ FILE *stdlis;
++FILE *stdrec;
+ static void backspace_output PARAMS ((void));
+ static int new_volume PARAMS ((enum access_mode));
+@@ -83,6 +84,9 @@
+ /* PID of child program, if compress_option or remote archive access.  */
+ static pid_t child_pid;
++/* Record number of the start of this block of records  */
++long baserec = 0 ;
++
+ /* Error recovery stuff  */
+ static int read_error_count;
+@@ -144,9 +148,11 @@
+ #endif /* DEBUG FORK */
++time_t start_time ;
+ void
+ init_total_written (void)
+ {
++  start_time = time(0);
+   clear_tarlong (total_written);
+   clear_tarlong (bytes_written);
+ }
+@@ -154,8 +160,12 @@
+ void
+ print_total_written (void)
+ {
++  time_t end_time = time(0);
+   fprintf (stderr, _("Total bytes written: "));
+   print_tarlong (total_written, stderr);
++  fprintf (stderr, _(" ("));
++  print_tarlong ((total_written/(end_time-start_time))>>10, stderr);
++  fprintf (stderr,"KB per second)");
+   fprintf (stderr, "\n");
+ }
+@@ -680,8 +690,48 @@
+ open_archive (enum access_mode access)
+ {
+   int backed_up_flag = 0;
++  time_t start_time = time(0) ;
+-  stdlis = to_stdout_option ? stderr : stdout;
++  stdrec = stdlis = to_stdout_option ? stderr : stdout;
++
++  if ( record_file_name != NULL )
++    {
++#define INSERT_TIMESTAMP
++#ifdef INSERT_TIMESTAMP
++      /*
++       * A record-file name with '%T' will be expanded with a decimal
++       * value for the timestamp of the archive. This is the time value
++       * stored in the label record.
++       * If you are using only one computer, this should be a unique number.
++       * You are able to create different rec-files for all your archives,
++       * as well as finding the index of your archive in a reliable way.
++       *
++       * Another way would be to let us set the timestamp by another option.
++       * tar --timestamp <ts-number> ...
++       */
++      char rfn[256];
++      if ( access == ACCESS_READ ) {
++        char*p= record_file_name ;
++        int i = 0 ;
++        int n;
++        while ( p[0] != '\0' ) {
++          if ( p[0] == '%' && p[1] == 'T' ) {
++            /* i += */ sprintf(rfn+i,"%d",start_time);
++            i = strlen(rfn) ;
++            p += 2 ;
++          } else { rfn[i++] = *p++ ; }
++        }
++        rfn[i] = '\0' ;
++      } else strcpy(rfn,record_file_name);
++#else
++      char*rfn=record_file_name;
++#endif
++      if ( ( stdrec = fopen(rfn,"w")) == NULL )
++        {
++          fprintf(stdlis,"Cannot open %s.\n",record_file_name);
++          exit(1);
++        }
++    }
+   if (record_size == 0)
+     FATAL_ERROR ((0, 0, _("Invalid value for record_size")));
+@@ -841,6 +891,46 @@
+   setmode (archive, O_BINARY);
+ #endif
++#if defined(MTIOCGET)
++  /* Prints the file number of the archive */
++  if ( block_number_option )
++    {
++      struct mtget get ;
++      int i ;
++      i = ioctl(archive,MTIOCGET,&get);
++      if (( i == 0 ) && ( get.mt_fileno >= 0 ))
++        {
++          fprintf(stdrec,
++            "loc             number of the file is %d \n",
++            get.mt_fileno );
++        }
++    }
++#endif
++
++#if defined(MTIOCPOS)
++  /* Prints the tape block number on every Linux SCSI-device */
++  if ( block_number_option )
++    {
++      struct mtpos pos ;
++      int i ;
++      i = ioctl(archive,MTIOCPOS,&pos);
++      if ( i == 0 )
++        {
++          fprintf(stdrec,
++            "loc             number of the first block is %d\n",
++            pos.mt_blkno );
++        }
++    }
++#endif
++
++  /* Prints the size of the blocks */
++  if ( block_number_option && blocking_factor != 20 )
++    {
++      fprintf(stdrec,
++        "loc             block length is %d bytes = %d * 512 bytes\n",
++      blocking_factor*512,blocking_factor);
++    }
++
+   switch (access)
+     {
+     case ACCESS_READ:
+@@ -874,7 +964,7 @@
+         assign_string (&current_file_name, record_start->header.name);
+         record_start->header.typeflag = GNUTYPE_VOLHDR;
+-        TIME_TO_OCT (time (0), record_start->header.mtime);
++        TIME_TO_OCT (start_time, record_start->header.mtime);
+         finish_header (record_start);
+ #if 0
+         current_block++;
+diff -ru tar-1.13/src/common.h tar-1.13.1/src/common.h
+--- tar-1.13/src/common.h      Wed Jul  7 08:07:30 1999
++++ tar-1.13.1/src/common.h    Mon Feb 21 23:30:56 2000
+@@ -311,6 +311,12 @@
+ /* Initial size of the sparsearray.  */
+ GLOBAL int sp_array_size;
++
++/* Time of writing.  */
++GLOBAL time_t start_time;
++
++/* File to write record information to. */
++GLOBAL char *record_file_name;
\f
+ /* Declarations for each module.  */
+@@ -327,7 +333,9 @@
+ /* Module buffer.c.  */
++extern long baserec;
+ extern FILE *stdlis;
++extern FILE *stdrec;
+ extern char *save_name;
+ extern off_t save_sizeleft;
+ extern off_t save_totsize;
+diff -ru tar-1.13/src/create.c tar-1.13.1/src/create.c
+--- tar-1.13/src/create.c      Wed Jul  7 07:27:04 1999
++++ tar-1.13.1/src/create.c    Sun Aug  6 22:29:50 2000
+@@ -435,11 +435,9 @@
+   uintmax_to_oct ((uintmax_t) sum, header->header.chksum, 7);
+-  set_next_block_after (header);
+-
+-  if (verbose_option
+-      && header->header.typeflag != GNUTYPE_LONGLINK
+-      && header->header.typeflag != GNUTYPE_LONGNAME)
++  if (verbose_option)
++      /* && header->header.typeflag != GNUTYPE_LONGLINK */
++      /* && header->header.typeflag != GNUTYPE_LONGNAME */
+     {
+       /* These globals are parameters to print_header, sigh.  */
+@@ -448,6 +446,9 @@
+       current_format = archive_format;
+       print_header ();
+     }
++
++  set_next_block_after (header);
++
+ }
\f
+ /* Sparse file processing.  */
+diff -ru tar-1.13/src/extract.c tar-1.13.1/src/extract.c
+--- tar-1.13/src/extract.c     Fri Jul  2 23:24:36 1999
++++ tar-1.13.1/src/extract.c   Mon Feb 21 21:32:07 2000
+@@ -962,6 +962,7 @@
+     case GNUTYPE_LONGNAME:
+     case GNUTYPE_LONGLINK:
+       ERROR ((0, 0, _("Visible long name error")));
++      print_header();
+       skip_file (current_stat.st_size);
+       if (backup_option)
+       undo_last_backup ();
+diff -ru tar-1.13/src/list.c tar-1.13.1/src/list.c
+--- tar-1.13/src/list.c        Wed Jul  7 07:46:52 1999
++++ tar-1.13.1/src/list.c      Sun Aug  6 22:25:28 2000
+@@ -124,7 +124,7 @@
+         if (block_number_option)
+           {
+             char buf[UINTMAX_STRSIZE_BOUND];
+-            fprintf (stdlis, _("block %s: ** Block of NULs **\n"),
++            fprintf (stdrec, _("block %s: ** Block of NULs **\n"),
+                      STRINGIFY_BIGINT (current_block_ordinal (), buf));
+           }
+@@ -138,7 +138,7 @@
+         if (block_number_option)
+           {
+             char buf[UINTMAX_STRSIZE_BOUND];
+-            fprintf (stdlis, _("block %s: ** End of File **\n"),
++            fprintf (stdrec, _("block %s: ** End of File **\n"),
+                      STRINGIFY_BIGINT (current_block_ordinal (), buf));
+           }
+         break;
+@@ -217,7 +217,7 @@
+         if (written > size)
+           written = size;
+         errno = 0;            /* FIXME: errno should be read-only */
+-        check = fwrite (data_block->buffer, sizeof (char), written, stdlis);
++        check = fwrite (data_block->buffer, sizeof (char), written, stdrec);
+         set_next_block_after ((union block *)
+                               (data_block->buffer + written - 1));
+         if (check != written)
+@@ -231,8 +231,8 @@
+       }
+       if (multi_volume_option)
+       assign_string (&save_name, NULL);
+-      fputc ('\n', stdlis);
+-      fflush (stdlis);
++      fputc ('\n', stdrec);
++      fflush (stdrec);
+       return;
+     }
+@@ -381,6 +381,8 @@
+         longp = ((header->header.typeflag == GNUTYPE_LONGNAME)
+                  ? &next_long_name
+                  : &next_long_link);
++          assign_string (&current_file_name, header->header.name);
++            print_header();
+         set_next_block_after (header);
+         if (*longp)
+@@ -763,10 +765,18 @@
+   int pad;
+   char *name;
++  extern union block *record_start;
++  extern union block *current_block;
++  if (block_number_option)
++    fprintf (stdrec, _("rec %10ld: "), baserec + (current_block - record_start));
++#if 0
++  annofile (stdrec, (char *) NULL);
++#endif
++
+   if (block_number_option)
+     {
+       char buf[UINTMAX_STRSIZE_BOUND];
+-      fprintf (stdlis, _("block %s: "),
++      fprintf (stdrec, _("block %s: "),
+              STRINGIFY_BIGINT (current_block_ordinal (), buf));
+     }
+@@ -778,11 +788,11 @@
+       if (quoted_name)
+       {
+-        fprintf (stdlis, "%s\n", quoted_name);
++        fprintf (stdrec, "%s\n", quoted_name);
+         free (quoted_name);
+       }
+       else
+-      fprintf (stdlis, "%s\n", current_file_name);
++      fprintf (stdrec, "%s\n", current_file_name);
+     }
+   else
+     {
+@@ -792,6 +802,11 @@
+       switch (current_header->header.typeflag)
+       {
+       case GNUTYPE_VOLHDR:
++          /* dirty bug fix to display the header processing
++           * tar cvvf /dev/null --label 'hello world' blah...
++           * J"org Weule weule@cs.uni-duesseldorf.de
++           */
++          current_stat.st_mtime = time_from_oct(current_block->header.mtime,1+12);
+         modes[0] = 'V';
+         break;
+@@ -804,8 +819,12 @@
+         break;
+       case GNUTYPE_LONGNAME:
++          modes[0] = 'L';
++          break;
++
+       case GNUTYPE_LONGLINK:
+-        ERROR ((0, 0, _("Visible longname error")));
++        /* ERROR ((0, 0, _("Visible longname error"))); */
++          modes[0] = 'K' ;
+         break;
+       case GNUTYPE_SPARSE:
+@@ -898,22 +917,22 @@
+       ugswidth = pad;
+ #if USE_OLD_CTIME
+-      fprintf (stdlis, "%s %s/%s %*s%s %s %s",
++      fprintf (stdrec, "%s %s/%s %*s%s %s %s",
+              modes, user, group, ugswidth - pad, "",
+              size, timestamp + 4, timestamp + 20);
+ #else
+-      fprintf (stdlis, "%s %s/%s %*s%s %s",
++      fprintf (stdrec, "%s %s/%s %*s%s %s",
+              modes, user, group, ugswidth - pad, "", size, timestamp);
+ #endif
+       name = quote_copy_string (current_file_name);
+       if (name)
+       {
+-        fprintf (stdlis, " %s", name);
++        fprintf (stdrec, " %s", name);
+         free (name);
+       }
+       else
+-      fprintf (stdlis, " %s", current_file_name);
++      fprintf (stdrec, " %s", current_file_name);
+       switch (current_header->header.typeflag)
+       {
+@@ -921,26 +940,26 @@
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, " -> %s\n", name);
++            fprintf (stdrec, " -> %s\n", name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, " -> %s\n", current_link_name);
++          fprintf (stdrec, " -> %s\n", current_link_name);
+         break;
+       case LNKTYPE:
+         name = quote_copy_string (current_link_name);
+         if (name)
+           {
+-            fprintf (stdlis, _(" link to %s\n"), name);
++            fprintf (stdrec, _(" link to %s\n"), name);
+             free (name);
+           }
+         else
+-          fprintf (stdlis, _(" link to %s\n"), current_link_name);
++          fprintf (stdrec, _(" link to %s\n"), current_link_name);
+         break;
+       default:
+-        fprintf (stdlis, _(" unknown file type `%c'\n"),
++        fprintf (stdrec, _(" unknown file type `%c'\n"),
+                  current_header->header.typeflag);
+         break;
+@@ -953,11 +972,11 @@
+       case FIFOTYPE:
+       case CONTTYPE:
+       case GNUTYPE_DUMPDIR:
+-        putc ('\n', stdlis);
++        putc ('\n', stdrec);
+         break;
+       case GNUTYPE_VOLHDR:
+-        fprintf (stdlis, _("--Volume Header--\n"));
++        fprintf (stdrec, _("--Volume Header--\n"));
+         break;
+       case GNUTYPE_MULTIVOL:
+@@ -965,15 +984,15 @@
+                 STRINGIFY_BIGINT
+                 (UINTMAX_FROM_OCT (current_header->oldgnu_header.offset),
+                  uintbuf));
+-        fprintf (stdlis, _("--Continued at byte %s--\n"), size);
++        fprintf (stdrec, _("--Continued at byte %s--\n"), size);
+         break;
+       case GNUTYPE_NAMES:
+-        fprintf (stdlis, _("--Mangled file names--\n"));
++        fprintf (stdrec, _("--Mangled file names--\n"));
+         break;
+       }
+     }
+-  fflush (stdlis);
++  fflush (stdrec);
+ }
+ /*--------------------------------------------------------------.
+@@ -996,7 +1015,7 @@
+       if (block_number_option)
+       {
+         char buf[UINTMAX_STRSIZE_BOUND];
+-        fprintf (stdlis, _("block %s: "),
++        fprintf (stdrec, _("block %s: "),
+                  STRINGIFY_BIGINT (current_block_ordinal (), buf));
+       }
+       name = quote_copy_string (pathname);
+diff -ru tar-1.13/src/names.c tar-1.13.1/src/names.c
+--- tar-1.13/src/names.c       Wed Jul  7 07:46:51 1999
++++ tar-1.13.1/src/names.c     Sun Aug  6 22:20:43 2000
+@@ -375,6 +375,14 @@
+           FATAL_ERROR ((0, errno, _("Cannot change to directory %s"),
+                         name_buffer));
+         chdir_flag = 0;
++          if ( record_file_name )
++            {
++              char *d = malloc(PATH_MAX);
++              if( d && getcwd(d,PATH_MAX) )
++                fprintf(stdrec,
++                        "loc             current directory is %s\n",
++                        d);
++            }
+       }
+       else if (change_dirs && strcmp (name_buffer, "-C") == 0)
+       chdir_flag = 1;
+diff -ru tar-1.13/src/tar.c tar-1.13.1/src/tar.c
+--- tar-1.13/src/tar.c Wed Jul  7 07:49:50 1999
++++ tar-1.13.1/src/tar.c       Tue Feb 22 00:27:07 2000
+@@ -132,6 +132,7 @@
+   SUFFIX_OPTION,
+   USE_COMPRESS_PROGRAM_OPTION,
+   VOLNO_FILE_OPTION,
++  RECORD_FILE_OPTION,
+   /* Some cleanup is being made in GNU tar long options.  Using old names is
+      allowed for a while, but will also send a warning to stderr.  Take old
+@@ -220,6 +221,7 @@
+   /* FIXME: --partial-blocks might be a synonym for --read-full-records?  */
+   {"record-number", no_argument, NULL, OBSOLETE_BLOCK_NUMBER},
+   {"record-size", required_argument, NULL, RECORD_SIZE_OPTION},
++  {"record-file", required_argument, NULL, RECORD_FILE_OPTION},
+   {"remove-files", no_argument, &remove_files_option, 1},
+   {"rsh-command", required_argument, NULL, RSH_COMMAND_OPTION},
+   {"same-order", no_argument, NULL, 's'},
+@@ -378,6 +380,7 @@
+       --checkpoint      print directory names while reading the archive\n\
+       --totals          print total bytes written while creating archive\n\
+   -R, --block-number    show block number within archive with each message\n\
++      --record-file     print the record information to file, enable -R\n\
+   -w, --interactive     ask for confirmation for every action\n\
+       --confirmation    same as -w\n"),
+            stdout);
+@@ -904,6 +907,11 @@
+       volno_file_option = optarg;
+       break;
++      case RECORD_FILE_OPTION:
++        record_file_name = optarg ;
++        block_number_option++;         /* Print block #s for debug */
++        break;
++
+       case USE_COMPRESS_PROGRAM_OPTION:
+       set_use_compress_program_option (optarg);
+       break;
+@@ -1155,14 +1163,52 @@
+       break;
+     case CREATE_SUBCOMMAND:
++
++/*
++ * Comment the next line out if you have problems. Joerg Weule
++ */
++#define PRINT_TROUPUT
++#ifdef PRINT_TROUPUT
++      start_time = time(0);
+       if (totals_option)
+-      init_total_written ();
++        init_total_written ();
++      create_archive ();
++      if (totals_option) {
++        time_t end_time = time(0);
++        double sec = end_time - start_time ;
++        /* double t = ((double)total_written) * BLOCKSIZE ; */
++      print_total_written ();
++        /*
++        fprintf (stderr, _("Total bytes written: %.0f"),t);
++        if ( t >= 1e9 ) fprintf(stderr, _(" (%3.1f Gb)"),t/1e9 ); else
++        if ( t >= 1e6 ) fprintf(stderr, _(" (%3.1f Mb)"),t/1e6 ); else
++        if ( t >= 1024 ) fprintf(stderr, _(" (%3.1f Kb)"),t/1024 );
++        fprintf(stderr,"\n");
++        if ( sec > 0.1 ){
++          long s, m, h = sec ;
++              m = h ;
++          h /= 3600 ;
++          m -= h * 3600 ;
++          s = m ;
++          m /= 60 ;
++          s -= m / 60 ;
++          fprintf (stderr, _("Elapsed time: %02d:%02d:%02d, %g sec\n"), h,m,s,sec);
++          if ( !flag_multivol)
++            fprintf (stderr, _("Throughput per second: %.0fKb/sec\n"),
++              t/sec/1024);
++        }
++        */
++      }
++#else
++      if (totals_option)
++        init_total_written ();
+       create_archive ();
+       name_close ();
+       if (totals_option)
+-      print_total_written ();
++        print_total_written ();
++#endif
+       break;
+     case EXTRACT_SUBCOMMAND:
diff --git a/zf-cre-open.c b/zf-cre-open.c
new file mode 100644 (file)
index 0000000..6b43449
--- /dev/null
@@ -0,0 +1,221 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ *
+ * Copyright: GPL
+ */
+
+/*
+ * If you compile this file with -DTEST, you will get a test program:
+ *
+ *     cc dds_fio.c -DTEST -o dds_fio && dds_fio
+ *
+ * The test shows the use of ccopen(...) to pipe stdout through /bin/grep.
+ *
+ * The interface should be useful in many cases.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mtio.h>
+#include <string.h>
+#include <unistd.h>            /* pipe() ... */
+#include <sys/types.h>         /* size_t, open() */
+#include <sys/wait.h>          /* wait() */
+#include <sys/stat.h>          /* open() */
+#include <fcntl.h>             /* open() */
+
+#include "zf-cre-open.h"
+
+#define streq(a,b) (!strcmp((a),(b)))
+
+FILE   *
+zfopen(
+             char const *const name,
+             int const compressed,
+             char const *const open_mode
+)
+{
+
+       FILE   *fp;
+       char   *b;
+
+       b = malloc(1024);
+       if (b == NULL)
+               exit(20);
+
+       if (compressed == T_MODE) {
+               if ((name != NULL) && (strcmp(name, "-"))) {
+                       fp = fopen(name, open_mode);
+                       if (fp == NULL) {
+                               perror("dds2tar");
+                               exit(21);
+                       }
+               } else if (streq(open_mode, "w")) {
+                       fp = stdout;
+               } else {
+                       fp = stdin;
+               }
+               return fp;
+       }
+       if (streq(open_mode, "w")) {
+               strcpy(b, "gzip ");
+               if ((name != NULL) && (strcmp(name, "-"))) {
+                       strcat(b, " > ");
+                       strcat(b, name);
+               }
+       } else if (streq(open_mode, "r")) {
+               strcpy(b, "gunzip --force --decompress --stdout ");
+               if ((name != NULL) && (strcmp(name, "-"))) {
+                       strcat(b, name);
+               }
+       }
+       fp = popen(b, open_mode);
+       if (fp == NULL) {
+               perror("dds2tar");
+               exit(22);
+       }
+       free(b);
+       return fp;
+}
+
+
+int
+cclose(int const fd)
+{
+       int     status = 0;
+
+       close(fd);
+       wait(&status);
+       return status;
+}
+
+int
+reopen(
+             int const stdfd,
+             char const *const output_file,
+             int const mode,
+             int const flags
+)
+{
+       int     fd;
+
+       if (!strcmp(output_file, "-")) {
+               /* use stdout */
+               fd = 1;
+       } else {
+               /* open file */
+               if ((fd = open(output_file, mode, flags)) == -1) {
+                       perror("dds2tar");
+                       exit(23);
+               }
+               /* don't know why this happens. Any idea? */
+               if (fd == 0) {  /* normally 0 is stdin!! */
+                       perror("dds2tar");
+                       exit(24);
+               }
+       }
+       if (0 <= stdfd) {
+               dup2(fd, stdfd);
+               close(fd);
+               fd = stdfd;
+       }
+       return fd;
+}
+
+/*
+ * creopen opens a pipe to a child process with the file number 'stdfd'
+ * on file number 'stdfd_child' of the child.
+ * The files are close as needed (see dup2(2)).
+ */
+
+int
+creopen(
+              int const stdfd_parent,  /* stdfd should not be == 3 */
+              int const stdfd_child,   /* stdfd_child must be 1 or 2 */
+              char const *const filename,
+              char const *const *argv
+)
+{
+       int     fd;
+       int     pid;
+       int     pipefd[2];
+       int     pipe_parent;
+
+       if ((stdfd_child & 0xfffffffe) != 0 || stdfd_child == stdfd_parent) {
+               fprintf(stderr, "creopen not useful with that parameters\n");
+               exit(25);
+       }
+       pipe_parent = stdfd_child ^ 1;
+       if (pipe(pipefd) < 0) { /* create pipe with two fd's */
+               perror("dds2tar");
+               exit(26);
+       }
+       if ((pid = fork()) == 0) {      /* we are the child process */
+               /* reconnect pipe to child */
+               dup2(pipefd[stdfd_child], stdfd_child);
+               close(pipefd[0]);       /* close input of pipe */
+               close(pipefd[1]);       /* close output of pipe */
+               /* the prototype of execv is wrong */
+               execv(filename, (char *const *) argv);
+               perror("dds2tar");
+               exit(27);
+       }
+       if (pid <= 0) {
+               perror("dds2tar");
+               exit(28);
+       }
+       /*
+        * We are the parent process.
+        */
+       close(stdfd_child);
+       fd = pipefd[pipe_parent];
+       if ((0 <= stdfd_parent) && (stdfd_parent <= 1)) {
+               dup2(fd, stdfd_parent);
+               close(fd);
+               fd = stdfd_parent;
+               close(pipefd[0]);
+               close(pipefd[1]);
+       }
+       return fd;
+}
+
+#ifdef TEST
+
+static char *a[] =
+{"grep", "allo", NULL};
+
+main(int argc, char **argv, char **envp)
+{
+
+       int     status;
+       int     pid;
+       int     fd;
+
+       if (!strcmp(argv[1], "-p")) {
+       } else {
+               if (!strcmp(argv[1], "-o"))
+                       reopen(1, argv[2], O_RDONLY, 0);
+               else
+                       creopen(1, 0, "/usr/bin/grep", a);
+               write(1, "Hallo World -1- \n", 17);
+               write(1, "Hi    World -2- \n", 17);
+               write(1, "Hallo World -3- \n", 17);
+               write(1, "Morgen Welt -4- \n", 17);
+               write(1, "Hallo World -5- \n", 17);
+               printf("Hallo World =1= \n");
+               printf("Hi    World =2= \n");
+               printf("Hallo World =3= \n");
+               printf("Morgen Welt =4= \n");
+               printf("Hallo World =5= \n");
+               fflush(stdout);
+               if (!strcmp(argv[1], "-o")) {
+                       close(1);
+               } else {
+                       cclose(1);
+               }
+       }
+}
+
+#endif
diff --git a/zf-cre-open.h b/zf-cre-open.h
new file mode 100644 (file)
index 0000000..3061a74
--- /dev/null
@@ -0,0 +1,46 @@
+
+/*
+ * This file is part of dds2tar.
+ * Copyright by J"org Weule
+ *
+ * Copyright: GPL
+ */
+
+#define C_MODE 1               /* compressed */
+#define T_MODE 0               /* transparent */
+
+/*
+ * Use popen and gzip to open a file with transparent compression.
+ * The mode may be "r" or "w".
+ */
+extern FILE *zfopen(
+                          char const *,        /* pathname */
+                          int const,   /* compression, e.g. 0 or 1 */
+                          char const *const    /* open mode, e.g. "r" or "w" */
+);
+
+/*
+ * Open a pipe to a child process on a given file number, e.g. 1.
+ *
+ * Example of a pipe to tar -t:
+ *                      static char * av[] = {"/bin/tar","-t",NULL};
+ *                      creopen(1,0,"/bin/tar",av,NULL);
+ */
+extern int creopen(
+                         int const,    /* file number of the parent */
+                         int const,    /* file number of the child */
+                         char const *const,    /* name of the program */
+                         char const *const *   /* argv of the program */
+
+);
+extern int cclose(int const);
+
+/*
+ * Open a file on a given file number, e.g. 1.
+ */
+extern int reopen(
+                        int const,     /* file number */
+                        char const *const,     /* name of the file */
+                        int const,     /* mode of the open */
+                        int const      /* file mode */
+);