From e4d5918466740011206c1e4dddc5da9ff69b1ebd Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 19 May 2008 23:00:10 -0600 Subject: [PATCH] Imported Upstream version 2.5.2 --- .indent.pro | 3 + COPYING | 339 +++++++++++++ Changes | 243 ++++++++++ Makefile | 231 +++++++++ README | 179 +++++++ dds-dd.man | 82 ++++ dds-dd.ps | 246 ++++++++++ dds2index.man | 132 +++++ dds2index.ps | 286 +++++++++++ dds2tar-test.sh | 153 ++++++ dds2tar.c | 846 +++++++++++++++++++++++++++++++++ dds2tar.h | 111 +++++ dds2tar.lsm | 26 + dds2tar.man | 363 ++++++++++++++ dds2tar.ps | 532 +++++++++++++++++++++ dds_chkhdr.c | 39 ++ dds_extract.c | 598 +++++++++++++++++++++++ dds_index.c | 245 ++++++++++ dds_quote.c | 47 ++ dds_tape.c | 475 ++++++++++++++++++ dds_tape.h | 30 ++ ddstool | 87 ++++ index-of-dds2index | 64 +++ index-of-tar | 66 +++ index-of-tar-t | 68 +++ index-of-tar-v | 65 +++ mt-dds.man | 174 +++++++ mt-dds.ps | 313 ++++++++++++ scsi_vendor | 75 +++ tar-1.11.2-sparse-files.README | 9 + tar-1.11.2-sparse-files.patch | 12 + tar-1.11.2.patch | 344 ++++++++++++++ tar-1.11.8.patch | 513 ++++++++++++++++++++ tar-1.12.patch | 487 +++++++++++++++++++ tar-1.13.patch | 540 +++++++++++++++++++++ zf-cre-open.c | 221 +++++++++ zf-cre-open.h | 46 ++ 37 files changed, 8290 insertions(+) create mode 100644 .indent.pro create mode 100644 COPYING create mode 100644 Changes create mode 100644 Makefile create mode 100644 README create mode 100644 dds-dd.man create mode 100644 dds-dd.ps create mode 100644 dds2index.man create mode 100644 dds2index.ps create mode 100755 dds2tar-test.sh create mode 100644 dds2tar.c create mode 100644 dds2tar.h create mode 100644 dds2tar.lsm create mode 100644 dds2tar.man create mode 100644 dds2tar.ps create mode 100644 dds_chkhdr.c create mode 100644 dds_extract.c create mode 100644 dds_index.c create mode 100644 dds_quote.c create mode 100644 dds_tape.c create mode 100644 dds_tape.h create mode 100755 ddstool create mode 100644 index-of-dds2index create mode 100644 index-of-tar create mode 100644 index-of-tar-t create mode 100644 index-of-tar-v create mode 100644 mt-dds.man create mode 100644 mt-dds.ps create mode 100755 scsi_vendor create mode 100644 tar-1.11.2-sparse-files.README create mode 100644 tar-1.11.2-sparse-files.patch create mode 100644 tar-1.11.2.patch create mode 100644 tar-1.11.8.patch create mode 100644 tar-1.12.patch create mode 100644 tar-1.13.patch create mode 100644 zf-cre-open.c create mode 100644 zf-cre-open.h diff --git a/.indent.pro b/.indent.pro new file mode 100644 index 0000000..f22fd9a --- /dev/null +++ b/.indent.pro @@ -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 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. + + 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.) + +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. + + 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. + + 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 + + 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. + + + Copyright (C) 19yy + + 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. + + , 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 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 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 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 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 ' 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 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`/ ../$(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 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 index 0000000..d8ad7d5 --- /dev/null +++ b/dds-dd.man @@ -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 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 index 0000000..e836388 --- /dev/null +++ b/dds2index.man @@ -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 index 0000000..6258d59 --- /dev/null +++ b/dds2index.ps @@ -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 index 0000000..d55ab8b --- /dev/null +++ b/dds2tar-test.sh @@ -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 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 /* getenv() */ +#include +#include /* strcmp() strlen() strstr() */ +#include /* open() stat() */ +#include /* stat() */ +#include /* open() */ +#include /* open() */ +#include /* 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] \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 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 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 + +#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 index 0000000..b7375bc --- /dev/null +++ b/dds2tar.lsm @@ -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 index 0000000..af262f8 --- /dev/null +++ b/dds2tar.man @@ -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 index 0000000..abfa127 --- /dev/null +++ b/dds2tar.ps @@ -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 index 0000000..39a6ba3 --- /dev/null +++ b/dds_chkhdr.c @@ -0,0 +1,39 @@ + +/* + * This file is part of dds2tar. + * Copyright by J"org Weule + */ + +#include +#include +#include +#include +#include +#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 index 0000000..45e7daf --- /dev/null +++ b/dds_extract.c @@ -0,0 +1,598 @@ + +/* + * This file is part of dds2tar. + * Copyright by J"org Weule + */ + +#include +#include +#include +#include +#include + +/* + * fnmatch() and FNM_LEADING_DIR + */ +#define _GNU_SOURCE 1 +#include + +#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 index 0000000..9c6949e --- /dev/null +++ b/dds_index.c @@ -0,0 +1,245 @@ + +/* + * This file is part of dds2tar. + * Copyright by J"org Weule + */ + +#include +#include +#include +#include +#include +#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 index 0000000..eecb836 --- /dev/null +++ b/dds_quote.c @@ -0,0 +1,47 @@ +#include +#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 index 0000000..3b7e526 --- /dev/null +++ b/dds_tape.c @@ -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 +#include /* fpirntf() */ +#include /* perror() */ +#include /* MTSEEK ... */ +#include /* ioctl() */ +#include /* 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 /* malloc() */ +#include /* printf() */ +#include /* ioctl() */ +#include /* memset() bcopy() */ +#include /* 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 index 0000000..d21540f --- /dev/null +++ b/dds_tape.h @@ -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 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 index 0000000..db5a547 --- /dev/null +++ b/index-of-dds2index @@ -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 index 0000000..30f64c9 --- /dev/null +++ b/index-of-tar @@ -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 index 0000000..310cd14 --- /dev/null +++ b/index-of-tar-t @@ -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 index 0000000..1f3d60a --- /dev/null +++ b/index-of-tar-v @@ -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 index 0000000..c4fef84 --- /dev/null +++ b/mt-dds.man @@ -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 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 index 0000000..ab96153 --- /dev/null +++ b/scsi_vendor @@ -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 index 0000000..410a8b0 --- /dev/null +++ b/tar-1.11.2-sparse-files.README @@ -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 index 0000000..4edefa6 --- /dev/null +++ b/tar-1.11.2-sparse-files.patch @@ -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 index 0000000..2ab19f1 --- /dev/null +++ b/tar-1.11.2.patch @@ -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 ... ++ */ ++ 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 index 0000000..462e852 --- /dev/null +++ b/tar-1.11.8.patch @@ -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 ... ++ */ ++ 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 (¤t_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 (¤t_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 index 0000000..7d1eec7 --- /dev/null +++ b/tar-1.12.patch @@ -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 ... ++ */ ++ 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 (¤t_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); + } + + /* 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 (¤t_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 index 0000000..d97879e --- /dev/null +++ b/tar-1.13.patch @@ -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 ... ++ */ ++ 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 (¤t_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; + + /* 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); ++ + } + + /* 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 (¤t_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 index 0000000..6b43449 --- /dev/null +++ b/zf-cre-open.c @@ -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 +#include +#include +#include +#include /* pipe() ... */ +#include /* size_t, open() */ +#include /* wait() */ +#include /* open() */ +#include /* 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 index 0000000..3061a74 --- /dev/null +++ b/zf-cre-open.h @@ -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 */ +); -- 2.30.2