From: Bdale Garbee Date: Tue, 20 May 2008 05:04:23 +0000 (-0600) Subject: Imported Upstream version 0.4b37 X-Git-Tag: upstream/0.4b37^0 X-Git-Url: https://git.gag.com/?p=debian%2Fdump;a=commitdiff_plain;h=6ca85a1b3c0486912b19bd5e47f78e9207ba5298 Imported Upstream version 0.4b37 --- 6ca85a1b3c0486912b19bd5e47f78e9207ba5298 diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..501bc16 --- /dev/null +++ b/CHANGES @@ -0,0 +1,1380 @@ +$Id: CHANGES,v 1.254 2004/07/07 13:34:06 stelian Exp $ + +Changes between versions 0.4b36 and 0.4b37 (released July 7, 2004) +================================================================== + +1. Added the --enable-staticz configure option which enables + dump and restore to be linked with static versions of + libz and libbz2 (and dynamic versions of all other libraries). + This will make Debian users happy, because libz and libbz2 + were the only needed libraries living in /usr, all the + others live in /lib. In case of system emergency, it is + better not to have to rely on an extra filesystem. + Thanks to Bdale Garbee for the suggestion. + +2. Fix compilation on (at least the Linux Debian port to) AMD64. + ( defines some types (__s64 and __u64) + that are also defined by () and + they conflict). + +3. Make dump's reading of the dumpdates file a bit more robust, + preventing dump from crashing when the dumpdates file has + been modified by hand. + +4. Fixed some offset calculations in dump code which could + lead to "bread lseek errors" on large filesystems. Thanks + to Bruce Lowekamp for + reporting this bug and debugging the issue. + +5. Made dump use the blkid library when searching for devices + by label or uuid instead of dump's own routines. + +6. Corrected a bug in dump where a wrong LABEL=... line in + /etc/fstab could prevent dump from dumping unrelated + filesystems. Thanks to Bruce Lowekamp + for reporting the bug. + +Changes between versions 0.4b35 and 0.4b36 (released April 21, 2004) +==================================================================== + +1. Fixed dump compilation with old gcc versions. Thanks to + Mike Castle for the patch. + +2. Fixed some warnings (howmany, roundup, powerof2 redefined) + when compiling against a recent glibc version. + +3. Fixed a bug in restore preventing the read of a dump tape + written with Solaris 7 ufsdump. Thanks to Patrick Higgins + for reporting the bug and providing + the test case. + +4. Changed dump to enable the creation of volumes of different + sizes in a single run (make -B accept a list of values). + Patch contributed by Florian Zumbiehl . + +5. Use the glibc provided minor() and major() macros instead + of our own bitmask implementation. This should be safe for + when the major/minor namespace will migrate to 32 bits. + Thanks to Zhang Jun for reporting + the bug. + +6. Made explicit in the dump man page that dump will not create + a remote file, it will only write to an already existing one. + +7. Another try at making size estimates better again. + +8. Put back the inconditional running of the end-of-tape + script which was changed in 0.434 to be run only when -M + or multiple -f were NOT specified. Some users rely on this + feature even when it is combined with -M/-f. + +9. Fixed restore when restoring huge backups (where rstdir... + temporary files are over 2GB). Thanks to + Raphael Jaffey for reporting this, + debugging the issue and making the patch. + +10. Made restore understand FreeBSD UFS2 tapes. Thanks to + David for submitting the bug + and providing a test case. + +11. Made dump work with an arbitrary integer level (no more 10 + levels only limitation). Thanks to Matthew + for the patch. + +Changes between versions 0.4b34 and 0.4b35 (released December 21, 2003) +======================================================================= + +1. Added a note in the dump man page saying that the default + blocksize can be 32 if -d is used with a high density argument. + Thanks to Antonios Christofides + for the patch. + +2. Fixed configure to correctly understand CPPFLAGS, CFLAGS, + LDFLAGS environment variables. Thanks to Arcady Genkin + for reporting the bug. + +3. Made -e/-E options of dump accept an unlimited number of inodes + to be excluded, rather than a hardcoded maximum. Thanks to + Dietrich Rothe for the patch. + +4. Updated the autoconf system to 2.50. Forced the -D_BSD_SOURCE + and -D_USE_BSD_SIGNAL defines in configure in order to solve + 64bit build problems because quad_t is redifined with a + different signature. Thanks to Mike Harris + for reporting this bug. + +5. Made restore build on Solaris, making possible to + restore Linux's "enhanced" tapes. Thanks to Uwe Gohlke + for the patch. + +6. Made an extension in the dump tape format capable of saving + MacOSX specific inode extensions. Uwe Gohlke + wrote the extension and contributed the restore code back + into this codebase. The same extension mechanism will be + used in the future to save ACLs... + +7. Made rmt work correctly with regard to QFA and local/remote + files and tapes. The remote access will however work only + when the dump provided rmt version is used. If you want to + use another rmt server, please do not use the QFA feature. + Thanks to Uwe Gohlke for the patch. + +Changes between versions 0.4b33 and 0.4b34 (released April 18, 2003) +==================================================================== + +1. Fixed the INSTALL file to reflect the actual install paths. + Thanks to David Ronis for + reporting the bug. + +2. Fixed the configure script to only check for headers presence + instead of trying to compile them. This should fix issues + with old build environments. Thanks to Kari Lempiainen + for reporting the bug. + +3. Fixed restore to correctly ignore sockets when comparing + a dump (as socket cannot be properly restored anyway). Thanks + to Gunther Reiszig for reporting the bug. + +4. Fixed restore to correctly access the archive file (-A argument) + even when using a remote tape. Thanks to Fabrice Bellet + for reporting the bug. + +5. Fixed (again) handling of long (largefile) seeks in rmt. + Thanks to Fabrice Bellet for reporting + the bug. + +6. Fixed restore corner case when dealing with large block sizes + dump is able to write now (-b 1024). Thanks to Fabrice Bellet + for reporting the bug. + +7. Fixed a bug preventing dump to access a filesystem having + a label exactly 16 bytes in length. Thanks to + for reporting the bug. + +8. Made dump store dump dates using explicit timezones, fixing a + problem with incremental dumps if the timezone is modified + between the dumps. Thanks to Philippe Troin for + the bug report and the patch. + +9. Fixed a bug encountered when dumping individual files (not full + filesystems or directories) and dangling symbolic links happen + to be in the list of files. For as far as dump is concerned, + dangling symbolic links are allowed, and are dumped as is. + Thanks to Jin-su Ahn for reporting the + bug and providing the fix. + +10. Fixed open and creation modes and permissions for QFA and + table-of-contents files in dump and restore. Thanks to + Philippe Troin for the patch. + +11. Fixed the archive file descriptor handling enabling it to be 0. + This can happen in some cases when shell redirections are used. + Thanks to Philippe Troin for the patch. + +12. Delayed the opening of archive file until after suid had been + dropped (fixing a possible security issue if dump is suid). + Thanks to Philippe Troin for the patch. + +13. Fixed the 'S' command handling in the rmt client part. + Thanks to Philippe Troin for the patch. + +14. Modified the end-of-tape script handling to print out statistics + (and stop the timer) before launching the eot script. Also, the eot + script does not get run anymore when using -M (which makes sense) or + when multiple tapes are listed on the command line + (-f tape0,tape1,tapen) (which also makes sense). + Thanks to Philippe Troin for the patch. + +15. Relicensed dump/restore under the 'revised' BSD license, as per + ftp://ftp.cs.berkeley.edu/ucb/4bsd/README.Impt.License.Change. + +16. Added LZO compression to dump. This new compression method has + the advantage of being super fast, thus not killing tape streaming + on slow machines. Thanks to Helmut Jarausch + for the patch and to + Markus Oberhumer for giving special permission + to include his miniLZO project (GPL licensed) in dump/restore. + +17. Some small buffer overruns fixes in rmt. Thanks to Antonomasia + for reporting the bugs. + +18. Added a special rmt version which can do encryption when writing + to tape. Read examples/encrypted_rmt/README for details on + how to enable and configure it. Thanks to Ken Lalonde + for the patch. + +19. Made dump work with 2.5 kernel end of tape early warning semantics. + Thanks to Kai Makisara for the patch. + +20. Fixed a bug which caused dump -w|-W not to work anymore, because + the fs_freq and fs_passno fields in /etc/mtab are always set + to 0 0. Thanks to Trent Piepho for + reporting the bug. + +Changes between versions 0.4b32 and 0.4b33 (released February 10, 2003) +======================================================================= + +1. Added a note in the restore man page clarifying the question + 'set the permissions on the current directory ?' asked by + restore at the end of treatment in -i and -x modes. + +2. Fixed the endianess issues when reading compressed tapes. + Thanks to Dark Force for + reporting this bug and providing test cases. + +3. Fixed the "ACL won't be dumped" warning message (which showed + an extra, unrelated error message). Thanks to Dragan Krnic + for reporting this bug. + +4. Made dump look first into /etc/mtab, then into /etc/fstab + when searching for filesystem paths. Also fixed some problems + caused by binding mounts or multiple block device mounts. + Thanks to Matus Uhlar , Elliott Mitchell + , Greg Edwards , + Brian Hoy . (fixes Debian bugs #147086 + and #160305, Sourceforge bugs #618699 and #679832). + +5. Made dump's -I option accept the value '0' meaning all the + read errors will be ignored. This can be useful when running + dump from unattended sessions (like cron jobs). Thanks to + John I Wang for the suggestion. + +6. Fixed the output of dump to indicate 'blocks' instead of + 'tape blocks' in the various messages (blocks are always + 1 Kilobyte, tape blocks are 1 BK * '-b' argument), and + made it clearly print the current blocksize at the start of + a dump. Thanks to Michal Szymanski for + the suggestions. + +7. Made rmt understand long (largefiles) seeks. + +8. Fixed build with very old versions of libext2fs, where + EXT2_FT_* constants were undefined. + +9. Made dump accept the dumpdates path on the command line + (-D file option) instead of using only the hardcoded one. + Thanks to Piete Brooks for the + suggestion. + +10. Enabled rmt, LFS, readline, QFA options by default in + ./configure. Updated the configure process (new versions + of config.guess, config.sub etc). + +Changes between versions 0.4b31 and 0.4b32 (released November 15, 2002) +======================================================================= + +1. Changed dump to use fcntl(F_SETLK) style locking instead + of flock() when locking the dumpdates file. With the old + locking scheme, a local user having read rights on the + dumpdates file could be able to do a Denial of Service attack + on dump. In order to lock the dumpdates file with the new + scheme, the user would need to have write access on the file. + Thanks to Richard Johnson for + reporting the bug (originally a bugtraq post). + +2. Fixed interactive 'ls' which caused spurious errors warnings + about 'undefined filetypes' detected. Thanks to Jorgen Ostling + for reporting this + bug. + +3. Fixed dump's estimate when dealing with sparse inodes. + +4. Modified dump to allow setting a blocksize bigger than 32kB + (raised the limit to 1024kB), because newer hardware needs + this for proper operation. Thanks to Dirk Traenapp + for reporting this. + +5. Fixed a bug causing Dump to stop and report an error if an + inode number in the exclude file was followed by some amount + of whitespace. Thanks to Jeffrey Sofferin + for reporting this bug. + +6. Fixed a bug which caused restore, in some particular cases, + to ask some 'scary' questions and leave a bunch of RSTTMP + directories behind when restoring incremental tapes. Thanks + to Philippe Troin for reporting this bug and + providing the test cases. + +7. Changed the wording when inodes are excluded from dump: + replaced 'Added inode 7 to exclude list' with + 'Excluding inode 7 (resize inode) from dump', as suggested + by Elliott Mitchell in a Debian bug report. + +Changes between versions 0.4b30 and 0.4b31 (released July 30, 2002) +=================================================================== + +1. Fixed rmt open flags transmission (GNU's symbolic syntax over + rmt) which I broke in 0.4b29. Thanks to Eros Albertazzi + for reporting the bug. + +Changes between versions 0.4b29 and 0.4b30 (released July 25, 2002) +=================================================================== + +1. Made dump print out the ext2 logical block number in case of a read + error, which can be given as an argument to debugfs' ncheck command, + in order to find out the affected inode. Added note about this + usage in dump's man page. + +2. Fixed a problem in restore when reading tapes written on big + endian machines with very old versions of dump. The patch was + contributed by George Helffrich . + +3. Fixed the tape length calculation when using large tapes + and compression. Thanks to Georg Lippold + for reporting the bug. + +4. Added a new set of examples in dump_on_cd_2 directory, based + on dump_on_cd examples but somewhat enhanced, supporting DVD + media, and localized in english and german. Thanks to + Georg Lippold for the new scripts. + +5. Made dump save 32 bit UID/GID. Internally, this was achieved + by switching from the old BSD inode format to the new BSD + inode format, which means that the tape format was changed. + However, since all restore versions out there should + transparently support both inode formats, the change should + have no side effects. Thanks to John Yu for + reporting the bug. + +6. Fixed a lot of warnings in the code shown when compiling + with 'gcc -W'. Thanks to Matthias Andree + for reporting this. + +7. Fixed a small markup bug in the dump man page. Thanks to + Eric S. Raymond for submitting the + patch. + +8. Rewrote entirely the man pages using the tmac.an macro + package (Linux man page format) instead of the original BSD + format. They should be now cleaner and easier to modify. + +Changes between versions 0.4b28 and 0.4b29 (released June 8, 2002) +================================================================== + +1. Fixed a problem in the rmt ioctl command, where ioctl's issued from + non Linux clients were misinterpreted. The description of the problem + (incompatible numbering in Linux mtio opcodes) is documented at + ftp://ftp.fokus.gmd.de/pub/unix/star/README.mtio . Thanks to + Jörg Schilling for reporting this bug and + providing an excellent, cross-platform replacement for rmt in his + star package. + +2. Fixed a bug reported by Andy Mentges + which caused restore to fail when the inode maps were not entirely + contained on the first volume (when using really small volumes or + when dumping a huge number of inodes). + +3. Fixed a problem in dump, where files in subdirectories of directories + that have the nodump flag set (or being excluded with -e/-E) were + sometimes incorrectly dumped (instead of being excluded). The original + fix is from David C Lawrence in the FreeBSD version + of dump: http://www.FreeBSD.org/cgi/query-pr.cgi?pr=32414 + Thanks to Ted Grzesik for reporting the bug and + help testing the patch. + +4. Added some example scripts from Gerd Bavendiek + which makes one able to pipe the output of dump, by the net, to + a remote CD-burner server. + +5. Made dump use O_CREAT|O_TRUNC both locally and remotely (over rmt), + and use GNU's symbolic syntax over rmt instead of numerical values + to assure multiple platform compatibility. + +6. Documented the -d option in restore. + +7. Added a -v (verbose) mode to dump. For now it just prints the number + of the inode being dumped, but this could evolve in future versions + to include interesting debugging output. + +8. Added a -o flag to restore, which automatically restores the current + directory permissions in -i or -x mode, without asking the operator + whether to do so. Patch submitted by Tony Clayton + and Peter Samuel . + +Changes between versions 0.4b27 and 0.4b28 (released April 12, 2002) +==================================================================== + +1. Fixed a bug in the QFA feature which could have caused + a bad tape positionning on restore (causing extra delays in + restore). Credits go to Uwe Gohlke . + +2. Added a small note in the dump man page specifying that + there should be no white space between the option letter and + the -j or -z parameter, thanks to Kenneth Porter + +3. Made restore work with older versions of the readline library, + by checking in configure for several extended symbols. Restore + can now be compiled with a readline as old as the 2.0 release + (though it may be a good idea to upgrade it to a more recent + version...). Thanks to Andrew Donkin for + reporting the build failures. + +4. Fixed a performance problem with the QFA file creation in + dump, which made unnecessary seeks on the tape slowing down + the dump. Thanks to Andrew Donkin for + reporting this issue. + +5. Removed the inclusion of some kernel headers in the dump + source, which prevented the compile in some kernel/glibc + headers/architecture combination. Thanks to Bdale Garbee + for reporting the bug. + +6. Added the appropriate error message when dump fails to + open the output file for writing. Thanks to Amith Varghese + for reporting this bug. + +7. Made restore able to understand large Solaris ufsdump tapes + (containing inodes bigger than 4194304). Sun have introduced + an "extension" to the dump tape format when dealing with + those inodes, which was uncorrectly handled by Linux restore. + Thanks to Uwe Gohlke for reporting the bug and + providing a test case. + +8. Added the -m parameter to dump which optimises the output for + inodes having been changed but not modified since the last dump + ('changed' and 'modified' have the meaning defined in stat(2)). + For those inodes, dump will save only the metadata, instead of + saving the entire inode contents. Inodes which are either + directories or have been modified since the last dump are saved + in a regular way. Uses of this flag must be consistent, meaning + that either every dump in an incremental dump set have the flag, + or no one has it. + +Changes between versions 0.4b26 and 0.4b27 (released February 15, 2002) +======================================================================= + +1. Fixed behaviour of dump when exceeding resource limits + (SIGXFSZ treatment). + +2. Added the -L flag to restore to allow the user to specify a + maximal allowed number of miscompares when using restore + with the -C option to check the backup. + +3. Detailed the manual entry for the -N option of restore. + +4. Added the -a flag to restore to make able doing unattended + restores in -i or -x mode (automatically walks through the + multiple dump volumes). + +5. Extended the QFA mode to work with local files and/or + remote tapes and files. This way, restore can know in advance + the tape number and the offset for the inodes to extract and + can minimize the extraction time by seeking directly to the + good tape/offset. + +6. Added the -A option to both dump and restore, + which makes dump to archive a dump table-of-contents in + the specified file to be used by restore to determine + whether a file is in the dump file that is being restored. + (the archive file syntax is also compatible with the + Solaris ufsdump generated one). + +7. Small fix in restore making it able to read some (broken ?) + Solaris ufsdump tapes. + +8. Fixed dump to correctly recognise the root filesystem when using + ext2 disk labels (LABEL=/). Thanks to John Yu + for reporting this bug. + +9. Added the -P option to restore to create a + Quick File Access file from an already made dump. Patch + contributed by Uwe Gohlke . + +10. Made restore compile and run on Solaris, making it a + possible replacement for the standard ufsrestore. Port was + contributed by Uwe Gohlke . + +Changes between versions 0.4b25 and 0.4b26 (released January 7, 2002) +===================================================================== + +1. Added a set of backup scripts from Eugenio Diaz + in the examples section. It features + automatic (cron based) full and incremental dumping of + several filesystems on a separate filesystem. + +2. Fixed a off-by-one miscalculation which disabled dumping + a one letter subdirectory. Thanks to Chris Siebenmann + for reporting the bug. + +3. Fixed several restore bugs occuring when trying to + restore some missing files on the tape. Thanks to Chris + Siebenmann for reporting the bug. + +4. Fixed --with-ldopts configure argument passing, installing from + a separate object directory, makefile cleanups contributed + by . + +5. Fix a bug which could caused, in some conditions, the highest + number inode of a filesystem, to not be dumped. Many thanks + to Chris Siebenmann for helping me + chase this bug. + +Changes between versions 0.4b24 and 0.4b25 (released November 17, 2001) +======================================================================= + +1. Added a mini howto from Patrick Walsh in the examples + directory. + +2. Minor man pages syntax corrections. Thanks to + Chris Danis for reporting the bugs. + +3. Added a script from David B. Peterson + to the examples section. It features dumping several + filesystems to a remote tape drive upon ssh. + +4. Added a patch provided by Richard Jones + which allows BRADEMAX (number of read errors tolerated by + dump) to be adjusted using the -I option. + +5. Fixed a bug which disabled doing "restore -C -f -". Thanks + to Clemens Stiglechner for the + patch. + +6. Add the -l option to restore to specify if, when doing a + remote restore, the file used to access the backup is a + regular file (the defaults being a tape drive). Restore needs + to know this information when reading a remote compressed + dump. Previously, this information was autodetected, but + the autodetection code fails (with ioctl: Inappropriate ioctl + for device) when using a non Linux remote box. Thanks to + many users and especially to Eros Albertazzi + for reporting this. + +7. Found a workaroung for the dump deadlock problem (3 childs + stuck in pause(), father in read()). The workaround seems + to work for me and several beta-testers. If it doesn't work + for you, please report back. + +8. Updated the RPM spec file (BuildPrereq, URL etc). + +Changes between versions 0.4b23 and 0.4b24 (released September 12, 2001) +======================================================================== + +1. Fixed the permissions of a newly created QFA file by dump. + +2. Cleaned up the source of dump (the external variables + definition was a complete mess, making possible to have + objects overlap). + +3. Fixed restore to use the full tape volume path when doing + a compare (since it changes the working directory to the + filesystem being compared in the process). + +4. Added the -q option to dump which makes dump abort + whenever it needs operator attention. It should be + easier to use dump in scripts with this option. + +5. Detect the use of incompatible options to dump and + refuse them (like -a and -B options together). + +6. Added bzip2 compression to dump/restore (use option -j level + to select it). Note that you will need a restore version + >= 0.4b24 in order to restore a bzip2 compressed dump. + The same warning as for the zlib compression applies: + the tape format of a bzip2 dump is not compatible with the + original BSD tape format. + +7. Fixed a overflow problem in dump corrupting the dump when + very large files were encountered. Thanks to Vladimir Nadvornik + for the bug report. + +8. Added a ioctl(BLKFLSBUF) in dump which should flush the + kernel buffer/page cache before starting the dump, helping + a bit those who use dump on mounted filesystems. Thanks to + John Yu and to Theodore T'so + for this suggestion. + +9. Updated the RPM spec file following the RedHat changes + (dynamically linked binaries now in /usr/sbin etc). + +10. Added a patch from Helmut Jarausch + which enables restore to recognise multi volume compressed dumps + done on CD. Included his scripts for dump (which pipe the dump + output directly into cdrecord) and restore. There is now + possible to to backups to CD on the fly! + +Changes between versions 0.4b22 and 0.4b23 (released July 20, 2001) +=================================================================== + +1. Fixed a buffer overflow in restore/tape.c. Patch provided by + Marcus Meissner (Caldera International Security Dept.). + +2. Implement the Sun rmt extended protocol. Patch submitted + by Ian Gordon . + +3. Check for the e2fsprogs header instead of + the linux kernel header. This ensures that dump always has the + latest version of this file. Patch submitted by + Andreas Dilger . + +4. Report any filesystem present in either /etc/fstab with a + positive passno or /etc/dumpdates in dump -w output. + Patch submitted by Andreas Dilger . + +5. Fixed the looping problem in dump introduced in the + previous version. + +6. Changed the -B option of dump to limit the size of + _compressed_ output per volume if compression is on. + Patch contributed by Helmut Jarausch + . Note however that, since + it is impossible to predict the size of the compressed + data before doing the compression, the -B limit is a bit + conservative. + +7. Fixed a bug in reading the operator typed file/tape path for + the next volume in restore. + +8. Implemented a "-F script" option to restore which permits the + user to specify a script which will be launched at the + beginning of each tape, useful for automatic programming of + tape changers for example. See the restore man page for the + script parameters and return codes. + +9. Small fix for the QFA routines provided by Uwe Gohlke + , and some recommendations for QFA uses in + the man pages. + +10. Fixed the multivolume restoring where making a mistake + to the 'Mount next tape' prompt caused several blocks to + be lost. + +11. Enhanced the -e option of dump to take as a parameter a + comma separated list of inode numbers. + +12. Added the -E option to dump which specify a file containing + inode numbers to exclude from the dump. + +13. Fixed the compressed multi-volume dump + restore. + +Changes between versions 0.4b21 and 0.4b22 (released May 12, 2001) +================================================================== + +1. Made dump report the number of blocks dumped per volume. + Thanks to Kenneth Porter for the suggestion. + +2. Fix a bug in dump where waiting too much at the 'change volumes' + question caused the volume to be rewritten. Thanks to + Graham Reed for reporting the + bug and providing a patch. + +3. Added a compression option to dump, contributed by Jerry + Peters . + + WARNING: the compression works only on files/pipes and + drives supporting variable block size. + + WARNING2: tapes created using the compression feature are + incompatible with the standard dump tape format, and a + version of restore >= 0.4b22 will be needed for extraction. + +4. Fixed some compilation problems for glibc 2.2.2 and 64 bit + architectures. Thanks to Paul Slootman for + the patch and to Bdale Garbee for forwarding + it upstream. + +5. Many cleanups (CPP defines, const char warnings, check of + ext2fs COMPAT flags, time_t cleanups, added libext2 version + in dump usage text) by Andreas Dilger . + +6. Made --prefix option work in configure. All the install path + are now based on the configure parameters. + +7. Added the Quick File Access mode in dump/restore, contributed + by Uwe Gohlke . In this mode, dump stores in + a file tape position for each inode, and this file is used by + restore (if called with parameter Q and the filename) + to directly position the tape at the file restore is currently + working on. This saves hours when restoring single files from + large backups, saves the tapes and the drive's head. Use + --enable-qfa option of configure to compile in the QFA support. + +8. Added the possibility to dump several files and directories + in a single invocation of dump. Thanks to Uwe Gohlke + for implementing this option. + +9. Fixed the dumping and restoring of files with holes + (files ending with holes didn't get dumped or restored + correctly). + +10. Fixed a socket descriptor leak in dump, which leaved opened + 3 file descriptors per dump process (and there is one dump + process per tape). + +11. Fixed dump large file system support, by explicit use of + open64/lseek64/etc functions (explicit use needed because + e2fsprogs libraries don't behave well when compiled with + FILE_OFFSET_BITS=64). + +Changes between versions 0.4b20 and 0.4b21 (released January 13, 2001) +====================================================================== + +1. Fixed some bugs in the dump -w|-W logic introduced by + the previous version. Thanks to Andreas Dilger + for his help on this one. + +2. Fixed again a compilation problem when using old e2fs + headers (filesystem label related). Thanks to many users + who reported this stupid error. + +3. Fixed a build problem on old lib5 based systems dealing with + _PATH_MNTTAB being undefined. Thanks to John Adams + for reporting the bug. + +4. Improved the error detection in restore when creating + the temporary files in TMPDIR. Now restore will corectly + report a 'no space left on device' error instead of + strange errors which could imply an archive corruption. + Thanks to Gabriel Somlo and + bgjenero for reporting the bug. + +5. Added the throughput information in dump's progression + messages. Thanks to Andreas Dilger + for the patch. + +6. Use libext2fs's inode scanning routines, which are particularly + robust when dealing with errors (especially when having some + bad blocks on the filesystem). Many thanks to Colin + for reporting the bug, investigating + the issues, finding a workaround, writing the patch and + fully testing it... (of course, if this patch will break + anything, he is to blame for :-)). + +7. Made dump and restore LFS aware. Dump can dump a filesystem + containing large files, generate a large file on output and + restore can restore them. This feature is not enabled by + default, use --enable-largefile option of configure to enable + it (you need to have a LFS aware glibc though). Thanks to + Andrea Arcangeli for submitting the patch, + and to Theodore T'so for his always + useful thoughts. + +8. Made dump ask upon a tape write error if it should rewrite + the current volume (assume this is a bad tape) or if it should + assume an end-of-tape condition (useful for tape drives which + behaves badly at the end of the tape). Thanks to Andreas + Dilger for the suggestion. + +Changes between versions 0.4b19 and 0.4b20 (released November 10, 2000) +======================================================================= + +1. Fixed a small compilation problem due to a change + in the definintion of the struct sigaction in + glibc 2.0 / libc5. Thanks to Gunther Schlegel + for reporting the bug and to + Dave Platt for suggesting + a fix. + +2. Modified the label and uuid analysis in order to be + self-contained (independant of kernel/libc headers). This + should fix the compile with older kernel/libc headers and + will preserve the functionality. Thanks to Bernhard Erdmann + for reporting the bug. + +3. The 'exclude inode' option, if applied to a directory + inode, excludes now correctly all the leaves of this + directory. Thanks to John R. Dennison + for reporting the bug. + +4. Fixed the '-e' option to disable the possibility + to exclude the root inode (which causes the dumps to + be unreadable by restore). Prevented array overflow + when multiple -e options are used. + +5. Fixed dump to correctly interpret a filesystem argument + which is a mountpoint and it is not an absolute path + (as specified in the fstab). Thanks to Bernhard R. Erdmann + for reporting the bug. + +6. Made dump able to backup files larger than 2 GB. Note that + dump still doesn't cope with files larger than 4 GB. + +7. Restore the real uid and gid before invoking an external + RSH program (big hole when dump or restore is suid root!). + +8. Get the values for the default tape device and the location + of fstab file from the system headers. Thanks to + Andreas Dilger for the patch. + +9. Made dump -w|-W report all recognized filesystems + present in either /etc/fstab or /etc/dumpdates, and present + the list in the same order as in fstab file. Thanks + to Andreas Dilger for the patch. + +10. Made dump's -a (automatic end of tape detection) the + default. Specifying one of -B, -c, -d or -s options will + override the EOM detection. Thanks to Andreas Dilger + for the patch. + +11. Save the ext2 filesystem label into the dump volume label. + Specifying a volume label on the command line (-L option) + will override this feature. Thanks to Andreas Dilger + for the patch. + +Changes between versions 0.4b18 and 0.4b19 (released August 20, 2000) +===================================================================== + +1. Fixed the signal handling in dump (which I broke in 0.4b17) + which was causing several strange dump failures (dump + hanged or segmentation faults etc). + +2. Specified the default blocksize in the dump man page. + +3. Changed two info messages of restore to be written on stdout + instead of stderr in order to leave stderr only for errors + or warnings. Thanks to Stephen Atwell + for the suggestion. + +4. Corrected an off by one calculation which prevented + dumping a directory having a 1 character name length. + Thanks to Bernhard Erdmann + for reporting the bug. + +5. Reinforce dump in order to allow only level 0 and no + -u option when dumping a subdirectory, and document + this in the man page. Thanks to Bernhard Erdmann + for reporting the bug. + +6. Fixed a small harmless bug in restore which caused + in some conditions hard links to be restored several + times (therefore generation some warning messages). + Thanks to Kenneth Porter for + reporting the bug. + +7. Updated the RPM spec file to the latest RedHat version, + providing FHS packaging and other cosmetic changes. + You will need RPM version >= 3.0.5 in order to build the RPM. + +8. Updated the configure script to check for libtermcap + before checking for libreadline, because we need this + library in order to compile the readline support. + +9. Made dump understand the LABEL= and UUID= notation + both in /etc/fstab and on the command line. Note that + you will need the /proc filesystem in order to use + these notations. Thanks to Erik Troan + for providing the patch. + +Changes between versions 0.4b17 and 0.4b18 (released June 30, 2000) +=================================================================== + +1. Fixed a potential buffer overflow in restore. Thanks + to Stan Bubrouski for reporting + the bug. + +2. Fixed a readline-related bug which prevented + 'cat DUMPFILE | restore -i -f -' from working. Thanks + to Charles Karney + for the bug report. + +3. Changed a few "panic" into "exit", causing restore to + be more stable against some attacks (like the last one + reported on Bugtraq, although the last version of restore + was not vulnerable - just dumped core). Thanks to + Andreas Hasenack for reporting + the bugs to me. + +4. Removed the suid-root bit on dump and restore in the + default build (and generated RPMs). It should be safer + now. Users who need the suid-root capabilities in order + to make network backups should read first the man page + of dump and enable the suid bit manually. + +5. Added -ltermcap to the compile parameters for restore + when using readline support, in order to make the compile + process work on some systems (SuSE ?). Thanks to + Patrik Schindler for reporting the bug. + +Changes between versions 0.4b16 and 0.4b17 (released June 1st, 2000) +==================================================================== + +1. The -F script is called now *only* at the end of a tape, + not at the end of the dump. Thanks to Christian Haul + for the bug report. + + Normally, the device name and the current volume number + are passed on the command line of the script. However, + if you want the old style script (with no arguments + passed on the command line), you can enable it in + configure with the --enable-oldstylefscript. + +2. Use posix signal handling to preserve dump functionality + with libc5. Thanks to Jeff Johnson for + the patch. + +3. Made the exit code of restore in case of a 'C'ompare + command reflect the result of the compare. An exit status + of 0 means the dump archive is correct, 1 means tape errors, + 2 means that some files were modified. Thanks to Kenneth Porter + for the suggestion. + +4. Made (finally) quotes work in interactive restore. + +5. Small fixes in order to allow dump to compile with a + really old e2fsprogs version. Thanks to Ian Zimmerman + for the bug report. + +6. Add GNU readline capabilities to interactive restore. + Use configure's --enable-readline flag to enable this feature. + Thanks to Patrik Schindler for the + suggestion. + +7. Do the compare on the fly in restore 'C' mode (this will + allow not to exhaust the available /tmp space when + ccmparing large files). Thanks to Kenneth Porter + for the suggestion. + +Changes between versions 0.4b15 and 0.4b16 (released March 11, 2000) +==================================================================== + +1. Fixed some several duplicate 'DUMP: DUMP:' in the + output of dump. + +2. Corrected the estimation of blocks to dump. Note that + this is still wrong for large directory inodes, due + to the size of a BSD directory entry on the tape + (estimation is based on the size of the ext2 directory, + which is smaller because it doesn't contain the null + character at the end). + +3. Made dump report the total number of MB written to + tape at the end of run. Thanks to W. Reilly Cooley + for the patch. + +4. Added the -X option to restore giving the possibility + to read the names of the files to be extracted/listed + from a text file (in addition of the command line). + Thanks to Dejan Muhamedagic for the + patch. + +5. Added the device name and the current volume number + as arguments to the end of tape script (dump -F option). + +6. Made the multi-volume dump work again (after having + broken it in 0.4b15). + +Changes between versions 0.4b14 and 0.4b15 (released March 2, 2000) +=================================================================== + +1. Added a prompt command in interactive restore mode. Thanks + to Andreas Dilger for the patch. + +2. Fixed a buffer overflow problem in dump (caused by + not checking the size of the filesystem parameter). + Thanks to Kim Yong-jun for + reporting this on Bugtraq (and to several dump users + who forwarded me his mail). + +3. Added the '-F script' option to dump in order to + launch a script at the end of each tape (to be used + with a tape changer, or to notify the sysadmin by + pager etc.). + +4. Fixed a bug in restore compare code caused by the changes + I made in 0.4b14. + +5. Fixed the treatment of options using the old BSD syntax + in both dump and restore. + +Changes between versions 0.4b13 and 0.4b14 (released February 10, 2000) +======================================================================= + +1. Fixed a bug in dump which may have caused invalid deleted + directories to be dumped out if they were deleted after the + mapping pass. This could occure on active filesystem and lead + to heap corruption (causing dump malfunction in many possible ways). + Thanks to Jan Sanislo for finding this + bug and submitting the patch. + +2. Fixed the handling of the filesystem parameter in dump. A + '/mnt/disk' parameter caused the disk contents to be dumped, + but a '/mnt/disk/' parameter caused the mountpoint directory + to be dumped (generally an empty directory). + +3. Improved the output of dump in order to tell which directory + it is currently dumping (when dumping a subtree). + +4. Added the '-e' exclude inode option to dump. Thanks to + Isaac Chuang for contributing with the patch. + +5. Added a REPORTING-BUGS file in order to provide a guide + on how to correctly report a bug in dump/restore. + +6. Fixed a restore problem when restoring a hard link to an inode + having the immutable or append-only attribute set. Thanks to + Ambrose Li for submitting the patch. + +7. Fixed a compatibility problem between dumps made on little + endian machines (the format was correct) and big endian + machines (the format was incorrect). This fix break the + compatibility with the older dumps made on big endian + machines (sparc, m86k, ppc etc). For the first time in + linux dump's history (I believe), the dumps made by *BSD, + Linux/alpha, Linux/sparc and Linux/x86 are compatible, + so interchangeable. Thanks to Rob Cermak + for submitting the bug and + helping me test the fix. + +8. Fixed the way dump reports the remaining percent/time, if + the number of blocks actually dumped exceeds the estimated + number of blocks. Thanks to Jean-Paul van der Jagt + for reporting the bug. + +Changes between versions 0.4b12 and 0.4b13 (released January 21, 2000) +====================================================================== + +1. Small Y2K fix in the man pages :). Thanks to Bernhard Sadlowski + for reporting the bug. + +2. Removed the requirement to build the RPM as root from the + spec file. Thanks to Christian Weisgerber + for submitting this. + +3. Fixed a bug in dump related to the 'filetype' feature of ext2fs, + causing dump to block when dumping really huge filesystems. + Many thanks to Patrik Schindler for + helping me find this bug. + +4. Fixed the treatment for an interrupt signal when dump access + the remote tape through RSH. Thanks to Christian Weisgerber + for providing the patch. + +5. Fixed a bug which was causing dump/restore to display + garbage characters instead of the remote host name. + +Changes between versions 0.4b11 and 0.4b12 (released January 8, 2000) +===================================================================== + +1. Small fix in the dump man page. Thanks to Thorsten Kukuk + for submitting the patch. + +2. Fix for the exit code when using the size estimate option of + dump. Thanks to Matti Taskinen for + submitting the patch. + +3. Handle EINTR in atomical reads/writes in dump, which was causing + dump to fail on some systems. Thanks to Eric Jergensen + for reporting the bug and submitting the patch. + +4. Handle more than 16 characters for the device names in dumpdates. + (up to 255 now). Thanks to Rainer Clasen for + tracking down the problem and proposing the solution. + +5. Fixed a bug in dump which prevented the creation of the + dumpdates file when doing a 0-level dump without already + having a dumpdates file. Thanks to Patrik Schindler + for reporting the bug. + +6. Changed the way dump 'S' flag reports the size estimate + from number of blocks into bytes (making it compatible + with the Solaris version, and simplifying things for + amanda users). Thanks to Jason L Tibbitts III + for reporting the bug. + +7. Fixed a compatibility problem in linux/alpha dump tape format. + Now the linux/alpha dump are (again) compatible with the + other dump formats. But this breaks compatibility with + older dumps made on alpha. Thanks to Mike Tibor + for helping me in finding this bug. + +Changes between versions 0.4b10 and 0.4b11 (released December 5, 1999) +====================================================================== + +1. Added a '--enable-kerberos' to configure. + +2. Added a 'S' option to dump which determines the amount of space + that is needed to perform the dump without actually doing it, similar + to the Sun's ufsdump 'S' option. Patch contributed by Rob Cermak + . + +3. Added a 'M' multi-volume option to dump and restore which enables + dumping to multiple files (useful when dumping to an ext2 + partition to make several dump files in order to bypass the 2GB + file size limitation). The 'f' argument is treated as a prefix and + the output files will be named 001, 002 etc. With + the 'M' flag, restore automatically selects the right file without + asking to enter a new tape each time. + +4. Fixed a memory leak which was causing dump to grow very big + (270MB when dumping a 10GB filesystem...). Thanks to Jason + Fearon for reporting the bug. + +Changes between versions 0.4b9 and 0.4b10 (released November 21, 1999) +====================================================================== + +1. Make configure test if the system glob routines support + extended syntax (ALTDIRFUNC). If not, use the internal glob + routines instead of system ones. Thanks to Bernhard Sadlowski + for reporting the bug + and helping me resolve this and other minor libc5 compiling + glitches. + +2. Fix a problem when dumping a ext2fs with the 'filetype' + feature enabled. Thanks to Patrick J. LoPresti + for reporting the bug and to + Theodore Y. Ts'o for providing the patch. + +3. Made the nodump flag work on directories. A directory which + has the nodump flag gets never dumped, regardless of its + contents. + +4. Integrate a patch from Jeremy Fitzhardinge + which allows dump on an active ext3 filesystem. However, this + is a "quick and dirty" patch which enables backup of an ext3 + filesystem through the ext2 compatibility (by ignoring the + NEEDS_RECOVERY bit). The journal file is not recognized and + it is dumped (it should not). + +5. Test the superblock compatibility flags when dumping, in order + to be sure that we know how to deal with specific features. + +Changes between versions 0.4b8 and 0.4b9 (released November 5, 1999) +==================================================================== + +1. Use lchown instead of chown, fixing a possible security problem + when restoring symlinks (a malicious user could use this + to deliberately corrupt the ownership of important system files). + Thanks to Chris Siebenmann for detecting + this and providing the patch. + +Changes between versions 0.4b7 and 0.4b8 (released November 3, 1999) +==================================================================== + +1. Put dump sources under CVS, added Id tags in all files so + one can use 'ident' on binary files. + +2. Added the dump/restore version in the usage text so one can + easily verify the version he is using. + +3. Small patch from Nuno Oliveira which fixes + a va_start/va_end problem on linux-ppc (always call va_start + va_end in pairs each time we use a vararg function). + +4. Added again the DT_* constants because old libc does not + contain them :(. Thanks to Eric Maisonobe + for submitting the bug report. + +5. Use ext2fs_llseek instead of llseek. With recent e2fsprogs + this should enable dumping big (huge) filesystems. + +6. Added the RSH environment variable in order to be able to + use a rsh replacement like ssh when doing remote backups (and + bypass the security limitations of rcmd). Now you can do remote + backups without being root (or making dump setuid root). + +7. Modified again the way dumpdates works. For incremental dumps, + we need to read dumpdates even if we are not using 'u' option. + Thanks to Bdale Garbee for his ideas on how + this should work. + +Changes between versions 0.4b6 and 0.4b7 (released October 8, 1999) +=================================================================== + +1. Removed the 'k' flag from the restore 'about' text if kerberos + was not compiled in. + +2. Prototyped (f)setflags from e2fsprogs and corrected the calls + to them (fsetflags takes a char*, setflags an open fd!). + +3. (f)setflags is called only if the flags aren't empty. If the + file is a special file, a warning is printed, because changing + flags implies opening the device. Normally, a special file + should not have any flag... (Debian bug #29775, patch provided + by Abhijit Dasgupta ). + +4. Made possible to dump a file system not mentioned in /etc/fstab. + (Debian bug #11904, patch provided by Eirik Fuller ). + +5. Changed the default behaviour to not create dumpdates + unless 'u' option is specified. Removed the old "debian-patch" + which provided the same thing. (Debian bug #38136, #33818). + +6. Removed all those dump*announce, since they were getting old... + +7. Added warning messages if dumpdates does not exist and + when an inferior level dump does not exist (except for a level 0 + dump). + +8. Debugged the glob calls in interactive mode: restore used a + dirent struct which was different from the /usr/include/dirent.h + one (this used to work, is it a glibc2 change?), so none of the + compat glob (which used /usr/include/dirent.h) or the system glob + worked. Restore use now the system dirent (and the system + DT_* constants), which are compatible with BSD ones. + +9. Added a configure flag (--with-dumpdatespath) to specify + the location of dumpdates file. By default, it is + /etc/dumpdates. + +10. Added the "AUTHOR" and "AVAILABILITY" sections and + included the current date/version in man pages. + +11. Corrected the estimation of remaining time when + the operator doesn't change the tapes quickly enough. This + was an old bug, I thought I corrected it, and discovered + that in fact it was corrected in two different places, so + the results canceled each other... + +Changes between versions 0.4b5 and 0.4b6 (released October 1, 1999) +=================================================================== + +1. Integrated multiple patches from RedHat, Debian and SuSE: + + - tweak dump/itime.c to not try to read dumpdates if the 'u' option + isn't specified. + - several fixes in the man pages. + - update the default tape device to /dev/st0. + - many updates for Linux Alpha (byte ordering, size_t etc). + - buffer overruns. + - use environment variable for TMPDIR (instead of /tmp). + - use sigjmp_buf instead of jmp_buf (RedHat bug #3260). + - workaround egcs bug (RedHat bugs #4281 and #2989). + - wire $(OPT) throughout Makefile's. + +2. Upgrade the dump revision to 1, making possible to dump filesystems + made with e2fsprogs-1.15 or newer. Nothing seems to break... + +3. Fix some compile warnings, prototype all functions. + +4. Use glibc err/glob instead of internal compatibility + routines (only if available). + +5. Fix a compile error on Linux 2.2.7 / libc5 (5.4.44) (patch provided + by Bernhard Sadlowski ). + +Changes between versions 0.4b4 and 0.4b5 (released September 22, 1999) +====================================================================== + +1. Integrated the changes from FreeBSD-3.1-RELEASE + (mostly bug fixes, buffer overruns, dump has now an "automatic + tape length calculation" flag, dump/restore can use kerberos now + (this is NOT tested), use environment variables for TAPE and + RMT etc.). + +2. Integrated three RedHat patches ("glibc", "kernel" and "bread" patches) + +3. Corrected a bug in restore when using 'C' option with multi-volumes + tapes (files splited accros two tapes give "size changed" errors + when comparing). + +4. Corrected the long standing bug when dumping multiple tapes. + This works for me, needs further testing. + +Changes between versions 0.4b3 and 0.4b4 (released January 17, 1997) +==================================================================== + +1. Dump now runs correctly on kernels 2.1.x + Fix made by Gerald Peters + +Changes between versions 0.4b2 and 0.4b3 +======================================== + +1. Use realpath() if available + +2. Report statistics + +Changes between versions 0.4b1 and 0.4b2 +======================================== + +1. Fixed the bug fix from Greg Lutz (I had made a mistake when integrating + the patch) + +2. Fixed restore to make it able to read FreeBSD 2.x dumps again + +3. Fixed configure.in to correctly handle --enable-rmt + +Changes between versions 0.3 and 0.4b1 +====================================== + +1. Integrated the changes from 4.4BSD-Lite2 + +2. Integrated the patches from Debian and Red Hat + +3. Portability changes: use the __u32, __u16, __s32, and __s16 types + +4. Changed dump to use the Ext2fs library to get block addresses. This + should solve the endianness problem on SparcLinux. + +5. Created a configure.in file (shamelessly stolen from the e2fsprogs + distribution's one) to use autoconf + +6. Fixed a few minor bugs + +Changes between versions 0.2e and 0.2f +====================================== + +1. Added the creation of named pipes (fifos) in restore. + +2. Added the -N flag in the restore manual page. + +3. Added the file kernel.patch which contains the llseek() optimization + patch for 1.2.x kernels. + +4. Fixed a bug in the restoration of symbolic links: owner and group were + not restored. + +5. Integrated some changes from FreeBSD 2.2. + +6. Added a call to ftruncate() after restoring each file to restore + correctly files ending by a hole. + +Changes between versions 0.2d and 0.2e +====================================== + +1. Fixed a bug in the "set owner/mode" process. Every file was restored + with owner = root (0) and group = root/wheel/whatever (0). + +Changes between versions 0.2c and 0.2d +====================================== + +1. Dump is now able to backup 2GB+ filesystems. + +2. Dump and restore can now be linked as static binaries. + +Changes between versions 0.2b and 0.2c +====================================== + +1. Fixed a bug when dumping ``slow'' (i.e. normal) symbolic links. + +Changes between versions 0.2a and 0.2b +====================================== + +1. Really fixed the bug that I should have corrected in 0.2a. + +2. Enabled optimization again. + +Changes between versions 0.2 and 0.2a +===================================== + +1. Disabled the optimization during compilation. + +Changes between versions 0.1 and 0.2 +==================================== + +1. Fixed a bug in fstab.c which caused a null pointer to be stored in + the fs_type field (actually, I modified the file fstab.c to make it + use the mntent functions). + +2. Dump and restore now use a 4.3 BSD compatible dump format. Backups + made by dump should be readable by the BSD restore and backups made + by the BSD dump should be readable by restore. Unfortunately, this + means that the dump format has changed between version 0.1 and version + 0.2 :-( + +3. Dump is now able to backup a subtree, it is no longer limited to whole + filesystems like the BSD version. + +4. Dump now uses ext2_llseek() so it is able to backup filesystems bigger + than 2 GB. + +Changes between versions 0.0 and 0.1 +==================================== + +1. Now create links rdump and rrestore during the `make install' step. + +2. Linux port specific bugs added to the manual pages + +3. Incorrect estimation of the number of tapes blocks fixed when doing + incremental backups. + +4. Better ls-like format in restore in interactive mode. diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..a9db587 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,36 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..00fdcef --- /dev/null +++ b/INSTALL @@ -0,0 +1,17 @@ +$Id: INSTALL,v 1.3 2003/02/11 08:57:41 stelian Exp $ + + Installation of the dump/restore port should be quite easy, since +a configure script is now provided. + + Configuration is made by running the configure script. Run +`configure --help' to get a list of options. + + After configuring the package, you can type `make' to compile the +programs, and `make install' to install the binaries in /usr/local/sbin and +the manual pages in `/usr/local/man/man8'. + + You need to have the latest Ext2fs programs installed on your system +since this version of dump uses the Ext2fs library written by Theodore T'so. +The Ext2fs programs are included in all Linux distributions (e2fsprogs and +e2fsprogs-dev[el] packages), or you can download the most up to date version +from http://e2fsprogs.sourceforge.net. diff --git a/KNOWNBUGS b/KNOWNBUGS new file mode 100644 index 0000000..e79ded9 --- /dev/null +++ b/KNOWNBUGS @@ -0,0 +1,17 @@ +$Id: KNOWNBUGS,v 1.5 1999/11/21 00:17:12 tiniou Exp $ + +Known bugs and limitations of the dump/restore port +=================================================== + +1. I have tried to minimize changes in the BSD source and some parts + may look ugly. dump/tape.c is really awfull but this is pure BSD + code :-) Maybe, I should replace it with a simpler and cleaner + version. + +2. Kerberos mode is _NOT_ tested. + +3. Some users related possible problems when dumping + active (mounted) filesystems. The problems are reported as + lseek and read error messages (with a negative count). If + you encounter this kind of problems, please report them + to the author. diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..b66b3e6 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,15 @@ +$Id: MAINTAINERS,v 1.4 2002/01/16 09:32:14 stelian Exp $ + +The dump and restore backup suit was ported to Linux's Second +Extended File System by Rémy Card + +He was the maintainer of the initial versions of dump (up and +including 0.4b4, released in january 1997). + +I decided to continue the developpement and release a new version. +Rémy didn't respond to any mail I sent to him, so I have +promoted myself as the new maintainer :) + +So, starting with 0.4b5, the new maintainer is me, +Stelian Pop . + diff --git a/MCONFIG.in b/MCONFIG.in new file mode 100644 index 0000000..e20399e --- /dev/null +++ b/MCONFIG.in @@ -0,0 +1,99 @@ +VERSION= 0.4b37 +DATE= July 7, 2004 + +AR= @AR@ +CC= @CC@ +INSTALL= @INSTALL@ +LD= @LD@ +LN_S= @LN_S@ +MV= @MV@ +RANLIB= @RANLIB@ +RM= @RM@ + +BINOWNER= @BINOWNER@ +BINGRP= @BINGRP@ +BINMODE= @BINMODE@ +MANOWNER= @MANOWNER@ +MANGRP= @MANGRP@ +MANMODE= @MANMODE@ + +INSTALLBIN= $(INSTALL) -o $(BINOWNER) -g $(BINGRP) -m $(BINMODE) +INSTALLMAN= $(INSTALL) -o $(MANOWNER) -g $(MANGRP) -m $(MANMODE) + +prefix= @prefix@ +exec_prefix= @exec_prefix@ +SBINDIR= @sbindir@ +MANDIR= @mandir@/man8 + +DUMPDATESPATH= @DUMPDATESPATH@ +# +# Global include directories +# +GINC= -I$(top_builddir) -I$(top_srcdir)/compat/include +# indicate where the ext2fs library can be found (this is not needed if you +# have run `make install-libs' in the e2fsprogs source directory). +#GINC+= -I/usr/src/e2fsprogs-0.5c/lib + +# +# Global libraries +# +# indicate where the ext2fs library can be found (this is not needed if you +# have run `make install-libs' in the e2fsprogs source directory). +#GLIBDIR= -L/usr/src/e2fsprogs-0.5c/lib +GLIBS= $(GLIBDIR) -L../compat/lib -lcompat -lext2fs -lcom_err + +# +# Definitions (don't change them unless you know what you are doing) +# +DEFS= -DRDUMP -DRRESTORE -DLINUX_FORK_BUG -DHAVE_LZO -D_PATH_DUMPDATES=\"$(DUMPDATESPATH)\" -D_DUMP_VERSION=\"$(VERSION)\" @OPTDEFS@ + +all:: + +# +# Autoconf magic +# + +$(top_builddir)/config.status: $(top_srcdir)/configure + (cd $(top_builddir); ./config.status --recheck) + +$(top_builddir)/MCONFIG: $(top_srcdir)/MCONFIG.in \ + $(top_builddir)/config.status + (cd $(top_builddir); ./config.status) + +$(top_builddir)/config.h: $(top_srcdir)/config.h.in \ + $(top_builddir)/config.status + (cd $(top_builddir); ./config.status) + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/MCONFIG \ + $(top_builddir)/config.status + (cd $(top_builddir); ./config.status) + +$(top_srcdir)/configure: $(top_srcdir)/configure.in + cd $(top_srcdir) && autoconf + +$(top_srcdir)/config.h.in: $(top_srcdir)/configure.in + cd $(top_srcdir) && autoheader + +# +# Make depend magic +# + +.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed + if test -n "$(SRCS)" ; then \ + $(CC) -M $(CFLAGS) $(SRCS) | \ + sed -f $(top_srcdir)/depfix.sed \ + -e 's; $(srcdir)/; $$(srcdir)/;g' \ + -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \ + -e 's; $(top_builddir)/; $$(top_builddir)/;g' \ + -e 's; \./; ;g' \ + -e '/^ *\\$$/d' > .depend; \ + else :; fi + +depend:: .depend + if test -n "$(SRCS)" ; then \ + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < Makefile | cat - .depend \ + > Makefile.new; \ + $(MV) Makefile Makefile.old; \ + $(MV) Makefile.new Makefile; \ + else :; fi diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..2dbd90a --- /dev/null +++ b/Makefile.in @@ -0,0 +1,24 @@ +srcdir= @srcdir@ +top_srcdir= @top_srcdir@ +top_builddir= . + +@MCONFIG@ + +RM= @RM@ +SUBDIRS= compat/lib compat/include common dump restore @RMTDIR@ + +all clean install dep depend realclean distclean:: + for i in $(SUBDIRS); do \ + (cd $$i && $(MAKE) $@) || exit 1; \ + done + +distclean:: + $(RM) -f config.status config.log config.cache + $(RM) -f MCONFIG Makefile config.h + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/README b/README new file mode 100644 index 0000000..1e96d8d --- /dev/null +++ b/README @@ -0,0 +1,10 @@ +$Id: README,v 1.3 1999/10/11 13:31:04 stelian Exp $ + + This is a test release of dump 0.4. + + See the file CHANGES for a list of changes from the previous version. + + See the file INSTALL for installation instructions. + + If you encounter problems with the dump and restore backup suite, +please contact the maintainers and send them a detailled bug report. diff --git a/REPORTING-BUGS b/REPORTING-BUGS new file mode 100644 index 0000000..479ae42 --- /dev/null +++ b/REPORTING-BUGS @@ -0,0 +1,57 @@ +Congratulations! You just found a bug in dump/restore and want +to know what to do next. + +Here are some guidelines you will want to follow before sending me +a mail: + +1. Are you sure it's a bug? If you just are not sure about how +to use a specific feature of dump, please post your question on +the dump-users mailing list. While you are there, try to browse the +archives of the mailing list and see if someone asked the same question +before. + + NOTE: questions about how to use the d(ensity) (b)locksize parameters + enters this category! + +2. Always test the last version of dump/restore before submitting a +bug report. Your problem is maybe already fixed! + +3. Consult the bugs using the bug system at sourceforge. Use this +bug system if you want to report a new bug or contribute to an +existing bug. You may want to create an account on sourceforge for that, +so the comments will automatically be forwarded to your email address. + +4. If you are using the bug system and didn't create an account on +sourceforge, put your email address into the bug report! If I am unable +to contact you for more information, chances are that the bug will +never be solved! + +5. Please provide detailed information about your system: + - distribution and its version (RedHat, Debian, Suse, homemade etc.) + - architecture (Intel, Sparc, PalmPilot etc.) + - dump/restore version (0.4b13, etc) + - e2fsprogs version (1.17, etc) + - libc version (libc5, glibc2.0, gilbc2.1 etc) + - complete output of the dump/restore command which caused + the failure (ok, you can delete the 'xx% done' lines) + - the device you dump into/restore from (tape drive, file etc). + - anything else you believe will help me to find the bug... + +6. In addition, if you want to report a bug on dump, provide also: + - details of your filesystem you want to dump: + output of the command 'tune2fs -l /dev/sda1' + (replace sda1 with your partition...) + - if your filesystem was mounted when doing the dump, try + to rerun the command with the filesystem unmounted. Does + the bug still occur? + - try to dump your filesystem using /dev/null as tape device. + This may help to know that the bug is not triggered by a + buggy device or tape or remote access problems. + + +Ok, here are the pointers you may want to access: + +Dump latest release: http://sourceforge.net/project/filelist.php?group_id=1306 +Dump mailing lists: http://sourceforge.net/mail/?group_id=1306 +Dump bug system: http://sourceforge.net/bugs/?group_id=1306 +My email: stelian@popies.net diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..3e2854c --- /dev/null +++ b/THANKS @@ -0,0 +1,134 @@ +$Id: THANKS,v 1.85 2004/07/01 09:14:48 stelian Exp $ + +Dump and restore were written by the people of the CSRG at the University +of California, Berkeley. + +They were ported to Linux by Remy Card , by using +the Ext2fs library, written by Theodore Ts'o . + +Kevin Layer added the comparison code in restore. + +Doug Paul helped me to make dump able to backup 2GB+ +filesystems. + +David Frey (the old Debian dump maintainer), +Bdale Garbee (the new Debian dump maintainer) and the people +from Red Hat Software provided lots of patches. + +Stelian Pop is now the current maintainer (since dump-0.4b5). + +Thanks to people who reported problems with the port, sent patches, and +suggested various improvements. +Here is a partial list of them (if I have forgotten someone, please complain): +John Adams johna@onevista.com +Jin-su Ahn jsahn@ee.snu.ac.kr +Eros Albertazzi eros@lamel.bo.cnr.it +Matthias Andree matthias.andree@stud.uni-dortmund.de +Andrea Arcangeli andrea@suse.de +Stephen Atwell satwell@urbana.css.mot.com +Gerd Bavendiek bav@epost.de +Fabrice Bellet fabrice@bellet.info +Stan Bubrouski satan@fastdial.net +Stephen Carr sgcarr@civeng.adelaide.edu.au +Mike Castle dalgoda@users.sourceforge.net +Rob Cermak cermak@ahab.rutgers.edu +Antonios Christofides A.Christofides@itia.ntua.gr +Isaac Chuang ike@isl.stanford.edu +Rainer Clasen bj@ncc.cicely.de +Tony Clayton tonyc@e-smith.com +W. Reilly Cooley wcooley@nakedape.cc +Chris Danis screechco@home.com +Abhijit Dasgupta abhijit@ans.net +John R. Dennison gerdesas@users.sourceforge.net +Eugenio Diaz getnito@yahoo.com +Andreas Dilger adilger@turbolinux.com +Andrew Donkin ard@waikato.ac.nz +Greg Edwards gedwards@users.sourceforge.net +Bernhard Erdmann bernhard.erdmann@gmx.de +Jason Fearon jasonf@netrider.org.au +Jeremy Fitzhardinge jeremy@goop.org +Eirik Fuller eirik@netcom.com +Arcady Genkin antipode@users.sourceforge.net +Uwe Gohlke uwe@ugsoft.de +Ian Gordon iangordon@users.sourceforge.net +Ted Grzesik tedgyz@roostme.com +Mike Harris mharris@redhat.com +Andreas Hasenack andreas@conectiva.com.br +Christian Haul haul@informatik.tu-darmstadt.de +George Helffrich george@geology.bristol.ac.uk +Patrick Higgins phiggins@transzap.com +Kjetil Torgrim Homme kjetilho@ifi.uio.no +Raphael Jaffey rjaffey@artic.edu +Jean-Paul van der Jagt jeanpaul@dutepp0.et.tudelft.nl +Helmut Jarausch jarausch@igpm.rwth-aachen.de +Eric Jergensen eric@dvns.com +Jeff Johnson jbj@redhat.com +Richard Johnson Richard.Johnson3@ey.com +Richard Jones rich@annexia.org +Zhang Jun zhangjun@nanjing-fnst.com +Charles Karney karney@users.sourceforge.net +Henry Katz hkatz@hkatz.dialup.access.net +Dragan Krnic dkrnic@lycos.com +Klaus Kudielka kkudielk@cacofonix.nt.tuwien.ac.at +Thorsten Kukuk kukuk@suse.de +Ken Lalonde ken@globalremit.com +Florian La Roche florian@jurix.jura.uni-sb.de +Kari Lempiainen kari@funky.pp.fi +Ambrose Li acli@mingpaoxpress.com +Georg Lippold g_lippold@sourceforge.net +Patrick J. LoPresti patl@cag.lcs.mit.edu +Bruce Lowekamp lowekamp@users.sourceforge.net +Greg Lutz greglutz@ix.netcom.com +Eric Maisonobe virnet@nat.fr +Kai Makisara Kai.Makisara@kolumbus.fi +Andy Mentges amentges@jumpline.com +David Miller davem@caip.rutgers.edu +Elliott Mitchell ehem@m5p.com +David Monro davidm@cs.su.oz.au +Dejan Muhamedagic dejan@quant-x.com +Lukas Nellen L.Nellen@ThPhys.Uni-Heidelberg.DE +Markus Oberhumer markus@oberhumer.com +Nuno Oliveira nuno@eq.uc.pt +Brent Olson night@halcyon.com +Jorgen Ostling jorgen_ostling@users.sourceforge.net +Jerry Peters gapeters@worldnet.att.net +David B. Peterson dave@toppledwagon.com +Trent Piepho xyzzy@speakeasy.org +Dave Platt dplatt@snulbug.mtview.ca.us +Kenneth Porter shiva@well.com +Eric S. Raymond esr@minx.thyrsus.com +Graham Reed greed@users.sourceforge.net +Gunther Reiszig gunther@mit.edu +David Ronis ronis@ronispc.chem.mcgill.ca +Dietrich Rothe d-rothe@users.sourceforge.net +Bernhard Sadlowski sadlowsk@Mathematik.Uni-Bielefeld.DE +Peter Samuel peters@e-smith.com +Jan Sanislo oystr@cs.washington.edu +Jörg Schilling schilling@fokus.gmd.de +Patrik Schindler poc@pocnet.net +Gunther Schlegel schlegel@riege.de +Chris Siebenmann cks@utcc.utoronto.ca +Paul Slootman paul@debian.org +Bob Snyder rsnyder@janet.advsys.com +Jeffrey Sofferin sofferin@users.sourceforge.net +Gabriel Somlo somlo@cs.colostate.edu +Clemens Stiglechner a9401816@unet.univie.ac.at +Michal Szymanski msz@astrouw.edu.pl +Matti Taskinen mkt@rni.helsinki.fi +Jason L Tibbitts III tibbs@math.uh.edu +Mike Tibor tibor@lib.uaa.alaska.edu +Dirk Traenapp dtraenapp@users.sourceforge.net +Erik Troan ewt@redhat.com +Philippe Troin phil@fifi.org +Theodore Y. Ts'o tytso@valinux.com +Stephen Tweedie sct@dcs.ed.ac.uk +Matus Uhlar uhlar@fantomas.sk +Amith Varghese amithv@yahoo.com +Daniel Veillard Daniel.Veillard@imag.fr +Jason Venner jason@idiom.com +John I Wang jiwang@users.sourceforge.net +Christian Weisgerber naddy@mips.rhein-neckar.de +Kim Yong-jun loveyou@hackerslab.org +John Yu jky@it.bu.edu +Ian Zimmerman itz@speakeasy.org +Florian Zumbiehl florz@gmx.de diff --git a/TODO b/TODO new file mode 100644 index 0000000..d3d4102 --- /dev/null +++ b/TODO @@ -0,0 +1,37 @@ +$Id: TODO,v 1.24 2002/01/25 14:59:53 stelian Exp $ + +Need to verify: +--------------- + +1. Verify that dump works with kerberos authentification (this + was ported from *BSD and was not tested - in fact, this + wasn't even compiled in!). Need success reports for this. + +Urgent items (for the next stable version): +------------------------------------------- + +All others: +----------- + +1. More documentation? Examples, crontab? + +2. Explore and correct dump problems on active filesystems + (lseek/read negative count) (This should be OK as of 0.4b14. + Unfortunately, this seems to continue for a very few users). + +3. Reimplement the ext2 specific code in a "backend" and + make the dump code more generic. This would allow creation + of other backends for other filesystems. Implementing a + (v)fat backend should be quite easy, as for BSD ffs (we + already have the code for this). The BSD code in traverse.c + (all those #ifdef _BSD) should go into the ffs backend. + +4. Implement a DEBUG option which doesn't fork on each tape, making + it able to debug dump with gdb. + +5. Make a bootable dump tape? I don't know if it is possible... + +6. EA/ACL support in dump (requested by Michael Ju. Tokarev + . + +7. Better readline completition in restore (escape spaces etc). diff --git a/common/Makefile.in b/common/Makefile.in new file mode 100644 index 0000000..80ea04d --- /dev/null +++ b/common/Makefile.in @@ -0,0 +1,33 @@ +# $Id: Makefile.in,v 1.5 2003/05/08 21:11:39 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= .. + +@MCONFIG@ + +INC= -I$(top_srcdir)/dump +ALL_CFLAGS= @CPPFLAGS@ @CFLAGS@ @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) @DUMPDEBUG@ +ALL_LDFLAGS= @LDFLAGS@ @LDOPTS@ @STATIC@ +SRCS= dumprmt.c +OBJS= dumprmt.o + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +all:: $(OBJS) + +install:: + +clean:: + $(RM) -f \#* *.s *.o *.a *~ core + +distclean:: clean + $(RM) -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/common/dumprmt.c b/common/dumprmt.c new file mode 100644 index 0000000..7f88f63 --- /dev/null +++ b/common/dumprmt.c @@ -0,0 +1,513 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: dumprmt.c,v 1.28 2003/10/26 16:05:45 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#elif defined sunos +#include + +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#include +#endif + +#ifdef __linux__ +#include +#endif + +#include +#include "dump.h" /* for X_STARTUP, X_ABORT etc */ + +#define TS_CLOSED 0 +#define TS_OPEN 1 + +static int rmtstate = TS_CLOSED; +static int tormtape = -1; +static int fromrmtape = -1; +int rshpid = -1; +static const char *rmtpeer = 0; + +static int okname __P((const char *)); +static OFF_T rmtcall __P((const char *, const char *)); +static void rmtconnaborted __P((int)); +static int rmtgetb __P((void)); +static int rmtgetconn __P((void)); +static void rmtgets __P((char *, size_t)); +static OFF_T rmtreply __P((const char *)); +static int piped_child __P((const char **command)); +#ifdef KERBEROS +int krcmd __P((char **, int /*u_short*/, char *, char *, int *, char *)); +#endif + +static int errfd = -1; +extern int dokerberos; +extern int ntrec; /* blocking factor on tape */ +extern int abortifconnerr; /* set to 1 if this lib should exit on connection errors + otherwise just print a message using msg */ +#ifndef errno +extern int errno; +#endif + +int +rmthost(const char *host) +{ + if (rmtpeer) + free((void *)rmtpeer); + if ((rmtpeer = strdup(host)) == NULL) + rmtpeer = host; + signal(SIGPIPE, rmtconnaborted); + return rmtgetconn(); +} + +static void +rmtconnaborted(UNUSED(int signo)) +{ + msg("Lost connection to remote host.\n"); + if (errfd != -1) { + fd_set r; + struct timeval t; + + FD_ZERO(&r); + FD_SET(errfd, &r); + t.tv_sec = 0; + t.tv_usec = 0; + if (select(errfd + 1, &r, NULL, NULL, &t)) { + int i; + char buf[2048]; + + if ((i = read(errfd, buf, sizeof(buf) - 1)) > 0) { + buf[i] = '\0'; + msg("on %s: %s%s", rmtpeer, buf, + buf[i - 1] == '\n' ? "" : "\n"); + } + } + } + if (abortifconnerr) + exit(X_ABORT); +} + +static int +rmtgetconn(void) +{ + char *cp; + const char *rmt; + static struct servent *sp = NULL; + static struct passwd *pwd = NULL; + const char *tuser; + const char *rsh; + int size; + int throughput; + int on; + char *rmtpeercopy; + + rsh = getenv("RSH"); + + if (!rsh && sp == NULL) { + sp = getservbyname(dokerberos ? "kshell" : "shell", "tcp"); + if (sp == NULL) { + if (abortifconnerr) { + errx(1, "%s/tcp: unknown service", dokerberos ? "kshell" : "shell"); + } else { + msg("%s/tcp: unknown service", dokerberos ? "kshell" : "shell"); + return 0; + } + } + } + if (pwd == NULL) { + pwd = getpwuid(getuid()); + if (pwd == NULL) { + if (abortifconnerr) { + errx(1, "who are you?"); + } else { + msg("who are you?"); + return 0; + } + } + } + if ((cp = strchr(rmtpeer, '@')) != NULL) { + tuser = rmtpeer; + *cp = '\0'; + if (!okname(tuser)) { + if (abortifconnerr) { + exit(X_STARTUP); + } else { + return 0; + } + } + rmtpeer = ++cp; + } else + tuser = pwd->pw_name; + if ((rmt = getenv("RMT")) == NULL) + rmt = _PATH_RMT; + msg(""); + + if (rsh) { + const char *rshcmd[6]; + rshcmd[0] = rsh; + rshcmd[1] = rmtpeer; + rshcmd[2] = "-l"; + rshcmd[3] = tuser; + rshcmd[4] = rmt; + rshcmd[5] = NULL; + + /* Restore the uid and gid. We really don't want + * to execute whatever is put into RSH variable with + * more priviledges than needed... */ + setuid(getuid()); + setgid(getgid()); + + if ((rshpid = piped_child(rshcmd)) < 0) { + msg("cannot open connection\n"); + return 0; + } + } + else { + /* Copy rmtpeer to rmtpeercopy to ignore the + return value from rcmd. I cannot figure if + this is this a bug in rcmd or in my code... */ + rmtpeercopy = (char *)rmtpeer; +#ifdef KERBEROS + if (dokerberos) + tormtape = krcmd(&rmtpeercopy, sp->s_port, tuser, rmt, &errfd, + (char *)0); + else +#endif + tormtape = rcmd(&rmtpeercopy, (u_short)sp->s_port, pwd->pw_name, + tuser, rmt, &errfd); + if (tormtape < 0) { + msg("login to %s as %s failed.\n", rmtpeer, tuser); + return 0; + } + size = ntrec * TP_BSIZE; + if (size > 60 * 1024) /* XXX */ + size = 60 * 1024; + /* Leave some space for rmt request/response protocol */ + size += 2 * 1024; + while (size > TP_BSIZE && + setsockopt(tormtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0) + size -= TP_BSIZE; + (void)setsockopt(tormtape, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)); + throughput = IPTOS_THROUGHPUT; + if (setsockopt(tormtape, IPPROTO_IP, IP_TOS, + &throughput, sizeof(throughput)) < 0) + perror("IP_TOS:IPTOS_THROUGHPUT setsockopt"); + on = 1; + if (setsockopt(tormtape, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) + perror("TCP_NODELAY setsockopt"); + fromrmtape = tormtape; + } + (void)fprintf(stdout, "Connection to %s established.\n", rmtpeer); + return 1; +} + +static int +okname(const char *cp0) +{ + const char *cp; + int c; + + for (cp = cp0; *cp; cp++) { + c = *cp; + if (!isascii(c) || !(isalnum(c) || c == '_' || c == '-')) { + warnx("invalid user name %s\n", cp0); + return (0); + } + } + return (1); +} + +int +rmtopen(const char *tape, const int mode) +{ + char buf[MAXPATHLEN]; + char *rmtflags; + + rmtflags = rmtflags_tochar(mode); + (void)snprintf(buf, sizeof (buf), "O%s\n%d %s\n", + tape, + mode & O_ACCMODE, + rmtflags); + free(rmtflags); + rmtstate = TS_OPEN; + return (rmtcall(tape, buf)); +} + +void +rmtclose(void) +{ + + if (rmtstate != TS_OPEN) + return; + rmtcall("close", "C\n"); + rmtstate = TS_CLOSED; +} + +int +rmtread(char *buf, size_t count) +{ + char line[30]; + int n, i; + ssize_t cc; + + (void)snprintf(line, sizeof (line), "R%u\n", (unsigned)count); + n = rmtcall("read", line); + if (n < 0) { + /* rmtcall() properly sets errno for us on errors. */ + errno = n; + return (-1); + } + for (i = 0; i < n; i += cc) { + cc = read(fromrmtape, buf+i, n - i); + if (cc <= 0) + rmtconnaborted(0); + } + return (n); +} + +int +rmtwrite(const char *buf, size_t count) +{ + char line[30]; + + (void)snprintf(line, sizeof (line), "W%ld\n", (long)count); + write(tormtape, line, strlen(line)); + write(tormtape, buf, count); + return (rmtreply("write")); +} + +OFF_T +rmtseek(OFF_T offset, int pos) +{ + char line[80]; + + (void)snprintf(line, sizeof (line), "L%lld\n%d\n", (long long)offset, pos); + return (rmtcall("seek", line)); +} + +struct mtget mts; + +struct mtget * +rmtstatus(void) +{ + int i; + char *cp; + + if (rmtstate != TS_OPEN) + return (NULL); + i = rmtcall("status", "S"); + if (i < 0) return NULL; + if (i != (int)sizeof(mts)) { + msg("mtget sizes different between host (%d) " + "and remote tape (%d)", sizeof(mts), i); + for ( /* empty */; i > 0; --i) + rmtgetb(); + return NULL; + } + for (i = 0, cp = (char *)&mts; i < (int)sizeof(mts); i++) + *cp++ = rmtgetb(); + return (&mts); +} + +int +rmtioctl(int cmd, int count) +{ + char buf[256]; + + if (count < 0) + return (-1); + (void)snprintf(buf, sizeof (buf), "I%d\n%d\n", cmd, count); + return (rmtcall("ioctl", buf)); +} + +static OFF_T +rmtcall(const char *cmd, const char *buf) +{ + + if (write(tormtape, buf, strlen(buf)) != (ssize_t)strlen(buf)) + rmtconnaborted(0); + return (rmtreply(cmd)); +} + +static OFF_T +rmtreply(const char *cmd) +{ + char *cp; + char code[30], emsg[BUFSIZ]; + + rmtgets(code, sizeof (code)); + if (*code == 'E' || *code == 'F') { + rmtgets(emsg, sizeof (emsg)); + msg("%s: %s", cmd, emsg); + errno = atoi(code + 1); + if (*code == 'F') + rmtstate = TS_CLOSED; + return (-1); + } + if (*code != 'A') { + /* Kill trailing newline */ + cp = code + strlen(code); + if (cp > code && *--cp == '\n') + *cp = '\0'; + + msg("Protocol to remote tape server botched (code \"%s\").\n", + code); + rmtconnaborted(0); + } + return (OFF_T)(atoll(code + 1)); +} + +static int +rmtgetb(void) +{ + char c; + + if (read(fromrmtape, &c, 1) != 1) + rmtconnaborted(0); + return (c); +} + +/* Get a line (guaranteed to have a trailing newline). */ +static void +rmtgets(char *line, size_t len) +{ + char *cp = line; + + while (len > 1) { + *cp = rmtgetb(); + if (*cp == '\n') { + cp[1] = '\0'; + return; + } + cp++; + len--; + } + *cp = '\0'; + msg("Protocol to remote tape server botched.\n"); + msg("(rmtgets got \"%s\").\n", line); + rmtconnaborted(0); +} + +int piped_child(const char **command) { + int pid; + int to_child_pipe[2]; + int from_child_pipe[2]; + + if (pipe (to_child_pipe) < 0) { + msg ("cannot create pipe: %s\n", strerror(errno)); + return -1; + } + if (pipe (from_child_pipe) < 0) { + msg ("cannot create pipe: %s\n", strerror(errno)); + return -1; + } + pid = fork (); + if (pid < 0) { + msg ("cannot fork: %s\n", strerror(errno)); + return -1; + } + if (pid == 0) { + if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0) { + msg ("cannot dup2 pipe: %s\n", strerror(errno)); + exit(1); + } + if (close (to_child_pipe[1]) < 0) { + msg ("cannot close pipe: %s\n", strerror(errno)); + exit(1); + } + if (close (from_child_pipe[0]) < 0) { + msg ("cannot close pipe: %s\n", strerror(errno)); + exit(1); + } + if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0) { + msg ("cannot dup2 pipe: %s\n", strerror(errno)); + exit(1); + } + setpgid(0, getpid()); + execvp (command[0], (char *const *) command); + msg("cannot exec %s: %s\n", command[0], strerror(errno)); + exit(1); + } + if (close (to_child_pipe[0]) < 0) { + msg ("cannot close pipe: %s\n", strerror(errno)); + return -1; + } + if (close (from_child_pipe[1]) < 0) { + msg ("cannot close pipe: %s\n", strerror(errno)); + return -1; + } + tormtape = to_child_pipe[1]; + fromrmtape = from_child_pipe[0]; + return pid; +} diff --git a/compat/include/Makefile.in b/compat/include/Makefile.in new file mode 100644 index 0000000..6fbfe48 --- /dev/null +++ b/compat/include/Makefile.in @@ -0,0 +1,24 @@ +# $Id: Makefile.in,v 1.4 2003/01/24 11:01:48 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= ../.. + +@MCONFIG@ + +all:: + +install:: + +clean:: + $(RM) -f \#* *~ core + +distclean:: clean + $(RM) -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/compat/include/bsdcompat.h b/compat/include/bsdcompat.h new file mode 100644 index 0000000..4b9b907 --- /dev/null +++ b/compat/include/bsdcompat.h @@ -0,0 +1,292 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: bsdcompat.h,v 1.23 2004/07/01 09:14:48 stelian Exp $ + */ + +#include +#include +#include +#include + +#define __dead volatile +#define UNUSED(x) x __attribute__ ((unused)) + +#ifndef NBBY +#define NBBY 8 +#endif + +#ifndef MIN +#define MIN(a,b) ((a < b) ? a : b) +#endif + +#define WINO 1 +#define DEV_BSIZE 512 +#define DEV_BSHIFT 9 + +#ifndef sunos +#define MAXBSIZE EXT2_MAX_BLOCK_SIZE +#define ROOTINO EXT2_ROOT_INO +#else +#define ROOTINO 2 +#endif +#ifdef EXT2_NODUMP_FL +#define UF_NODUMP EXT2_NODUMP_FL +#endif + +#ifndef howmany +#define howmany(x,y) (((x)+((y)-1))/(y)) +#endif +#ifndef roundup +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) +#endif +#ifndef powerof2 +#define powerof2(x) ((((x)-1)&(x))==0) +#endif + +#define fsbtodb(sb,b) ((ext2_loff_t)(((long long)(b) * EXT2_BLOCK_SIZE((sb)->super)) / DEV_BSIZE)) +#define dbtofsb(sb,b) ((int)(((long long)(b) * DEV_BSIZE) / EXT2_BLOCK_SIZE((sb)->super))) + +#define sblock fs +#define fs_fsize fragsize +#define fs_bsize blocksize +#define fs_size super->s_blocks_count + +#define IFMT S_IFMT +#define IFLNK S_IFLNK +#define IFREG S_IFREG +#define IFDIR S_IFDIR +#define IFCHR S_IFCHR +#define IFBLK S_IFBLK +#define IFSOCK S_IFSOCK +#define IFIFO S_IFIFO + +#if 0 +typedef __s64 quad_t; +typedef __u64 u_quad_t; +#endif + +/* + * The BSD dump format reserves 4 bytes for a time_t, but other architectures + * (notably axp) have larger time_t. ctime4() is a modified ctime() which + * always accepts short 4-byte times. + */ +#define ctime4(timep) ({ time_t t = *(timep); ctime(&t); }) + +/* + * This is the ext2_inode structure but the fields have been renamed + * to match 4.4BSD's names + */ +#define NDADDR 12 +#define NIADDR 3 + +#define NINDIR(fs) EXT2_ADDR_PER_BLOCK(fs->super) + +#ifdef sunos +typedef uint8_t __u8; +typedef uint16_t __u16; +typedef uint32_t __u32; +typedef int8_t __s8; +typedef int16_t __s16; +typedef int32_t __s32; +#ifndef u_int +typedef unsigned int u_int; +#endif +#ifndef u_int16_t +typedef unsigned short u_int16_t; +#endif +#ifndef u_char +typedef unsigned char u_char; +#endif +typedef int64_t quad_t; +#endif /* sunos */ + +struct dinode { + __u16 di_mode; + __u16 di_uid; + __u32 di_size; + __u32 di_atime; + __u32 di_ctime; + __u32 di_mtime; + __u32 di_dtime; + __u16 di_gid; + __u16 di_nlink; + __u32 di_blocks; + __u32 di_flags; + __u32 di_reserved1; + __u32 di_db[NDADDR]; + __u32 di_ib[NIADDR]; + __u32 di_gen; + __u32 di_file_acl; + __u32 di_dir_acl; + __u32 di_faddr; + __u8 di_frag; + __u8 di_fsize; + __u16 di_pad1; + __u16 di_uidhigh; + __u16 di_gidhigh; + __u32 di_spare; +}; + +#define di_rdev di_db[0] +/* #define di_ouid di_uid */ +/* #define di_ogid di_gid */ +#define di_size_high di_dir_acl + +/* + * This is the ext2_dir_entry structure but the fields have been renamed + * to match 4.4BSD's names + * + * This is the 4.4BSD directory entry structure + */ +#define DIRBLKSIZ DEV_BSIZE +#ifndef MAXNAMLEN +#define MAXNAMLEN 255 +#endif + +#ifdef sunos +#define MAXNAMLEN 255 +#endif + +/* + * For old libc. + */ +#ifndef DT_UNKNOWN +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 + +#ifdef sunos +#define DT_WHT 14 +#endif +#endif + +#ifndef d_fileno +#define d_fileno d_ino +#endif + +/* + * The direct structure used by dump/restore. + */ +struct direct { + __u32 d_ino; + __u16 d_reclen; + __u8 d_type; + __u8 d_namlen; + char d_name[MAXNAMLEN + 1]; +}; +/* + * Convert between stat structure types and directory types. + */ +#define IFTODT(mode) (((mode) & 0170000) >> 12) +#define DTTOIF(dirtype) ((dirtype) << 12) + +/* + * The DIRSIZ macro gives the minimum record length which will hold + * the directory entry. This requires the amount of space in struct direct + * without the d_name field, plus enough space for the name with a terminating + * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary. + */ +#ifdef __linux__ +#if 0 +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define DIRSIZ(oldfmt, dp) \ + ((oldfmt) ? \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_type+1 + 3) &~ 3)) : \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))) +#else /* BYTE_ORDER */ +#define DIRSIZ(oldfmt, dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +#endif +#else /* 0 */ +#define DIRSIZ(oldfmt,dp) EXT2_DIR_REC_LEN(((dp)->d_namlen & 0xff) + 1) +#endif +#else /* __linux__ */ +#define DIRSIZ(oldfmt, dp) \ + ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) +#endif + +/* + * This is the old (Net/2) BSD inode structure + * copied from the FreeBSD 1.1.5.1 include file + */ +#define MAXFASTLINK (((NDADDR + NIADDR) * sizeof(unsigned long)) - 1) + +struct old_bsd_inode { + __u16 di_mode; + __s16 di_nlink; + __u16 di_uid; + __u16 di_gid; +#if 1 + union { + u_quad_t v; + __u32 val[2]; + } di_qsize; +#else + u_quad_t di_size; +#endif + __u32 di_atime; + __s32 di_atspare; + __u32 di_mtime; + __s32 di_mtspare; + __u32 di_ctime; + __s32 di_ctspare; +#if 0 + union { + struct { + daddr_t di_udb[NDADDR]; + daddr_t di_uib[NIADDR]; + } di_addr; + char di_usymlink[MAXFASTLINK + 1]; + } di_un; +#else + __u32 di_db[NDADDR]; + __u32 di_ib[NIADDR]; +#endif + __s32 di_flags; + __s32 di_blocks; + __s32 di_gen; + __u32 di_spare[4]; +}; + +struct bsdtimeval { /* XXX alpha-*-linux is deviant */ + __u32 tv_sec; + __u32 tv_usec; +}; + +/* + * This is the new (4.4) BSD inode structure + * copied from the FreeBSD 2.0 include file + */ +struct new_bsd_inode { + __u16 di_mode; + __s16 di_nlink; + union { + __u16 oldids[2]; + __u32 inumber; + } di_u; + u_quad_t di_size; + struct bsdtimeval di_atime; + struct bsdtimeval di_mtime; + struct bsdtimeval di_ctime; + __u32 di_db[NDADDR]; + __u32 di_ib[NIADDR]; + __u32 di_flags; + __s32 di_blocks; + __s32 di_gen; + __u32 di_uid; + __u32 di_gid; + __s32 di_spare[2]; +}; + +#define di_ouid di_u.oldids[0] +#define di_ogid di_u.oldids[1] diff --git a/compat/include/bylabel.h b/compat/include/bylabel.h new file mode 100644 index 0000000..baa334a --- /dev/null +++ b/compat/include/bylabel.h @@ -0,0 +1,41 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * 2000-01-20 James Antill + * - Added error message if /proc/partitions cannot be opened + * 2000-05-09 Erik Troan + * - Added cache for UUID and disk labels + * Wed Aug 16 2000 Erik Troan + * - Ported to dump/restore + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: bylabel.h,v 1.6 2004/07/05 15:02:36 stelian Exp $ + */ + +#ifndef _BYLABEL_H_ +#define _BYLABEL_H_ + +#include + +#ifdef HAVE_BLKID + +#include + +static inline const char * get_device_name(const char * item) { + return blkid_get_devname(NULL, item, NULL); +} + +static inline const char * get_device_label(const char * spec) { + return blkid_get_tag_value(NULL, "LABEL", spec); +} + +#else + +const char * get_device_name(const char * item); +const char * get_device_label(const char * spec); + +#endif + +#endif /* !_BYLABEL_H_ */ diff --git a/compat/include/compaterr.h b/compat/include/compaterr.h new file mode 100644 index 0000000..14e6671 --- /dev/null +++ b/compat/include/compaterr.h @@ -0,0 +1,88 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: compaterr.h,v 1.10 2003/03/30 15:40:34 stelian Exp $ + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _COMPATERR_H_ +#define _COMPATERR_H_ + +#include + +#if defined(HAVE_ERR) || defined(HAVE_ERRX) || defined(HAVE_VERR) || defined(HAVE_VERRX) || defined(HAVE_VWARN) || defined(HAVE_VWARNX) || defined(HAVE_WARN) || defined(HAVE_WARNX) +#include +#endif + +#include + +#include + +#ifndef _BSD_VA_LIST_ +#define _BSD_VA_LIST_ va_list +#endif + +#ifndef __dead +#define __dead volatile +#endif + +__BEGIN_DECLS +#ifndef HAVE_ERR +__dead void err __P((int, const char *, ...)); +#endif +#ifndef HAVE_VERR +__dead void verr __P((int, const char *, _BSD_VA_LIST_)); +#endif +#ifndef HAVE_ERRX +__dead void errx __P((int, const char *, ...)); +#endif +#ifndef HAVE_VERRX +__dead void verrx __P((int, const char *, _BSD_VA_LIST_)); +#endif +#ifndef HAVE_WARN +void warn __P((const char *, ...)); +#endif +#ifndef HAVE_VWARN +void vwarn __P((const char *, _BSD_VA_LIST_)); +#endif +#ifndef HAVE_WARNX +void warnx __P((const char *, ...)); +#endif +#ifndef HAVE_VWARNX +void vwarnx __P((const char *, _BSD_VA_LIST_)); +#endif +__END_DECLS + +#endif /* !_COMPATERR_H_ */ diff --git a/compat/include/compatglob.h b/compat/include/compatglob.h new file mode 100644 index 0000000..df2a536 --- /dev/null +++ b/compat/include/compatglob.h @@ -0,0 +1,100 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: compatglob.h,v 1.9 2003/03/30 15:40:34 stelian Exp $ + */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _COMPATGLOB_H_ +#define _COMPATGLOB_H_ + +#include + +#ifdef HAVE_GLOB +#include +#else + +#include + +struct stat; +typedef struct { + int gl_pathc; /* Count of total paths so far. */ + int gl_matchc; /* Count of paths matching pattern. */ + int gl_offs; /* Reserved at beginning of gl_pathv. */ + int gl_flags; /* Copy of flags parameter to glob. */ + char **gl_pathv; /* List of paths matching pattern. */ + /* Copy of errfunc parameter to glob. */ + int (*gl_errfunc) __P((const char *, int)); + + /* + * Alternate filesystem access methods for glob; replacement + * versions of closedir(3), readdir(3), opendir(3), stat(2) + * and lstat(2). + */ + void (*gl_closedir) __P((void *)); + struct dirent *(*gl_readdir) __P((void *)); + void *(*gl_opendir) __P((const char *)); + int (*gl_lstat) __P((const char *, struct stat *)); + int (*gl_stat) __P((const char *, struct stat *)); +} glob_t; + +#define GLOB_APPEND 0x0001 /* Append to output from previous call. */ +#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ +#define GLOB_ERR 0x0004 /* Return on error. */ +#define GLOB_MARK 0x0008 /* Append / to matching directories. */ +#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ +#define GLOB_NOSORT 0x0020 /* Don't sort. */ + +#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ +#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */ +#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */ +#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ +#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ +#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ + +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABEND (-2) /* Unignored error. */ + +__BEGIN_DECLS +int glob __P((const char *, int, int (*)(const char *, int), glob_t *)); +void globfree __P((glob_t *)); +__END_DECLS + +#endif /* HAVE_GLOB */ + +#endif /* !_COMPATGLOB_H_ */ diff --git a/compat/include/compatlfs.h b/compat/include/compatlfs.h new file mode 100644 index 0000000..fe7db5f --- /dev/null +++ b/compat/include/compatlfs.h @@ -0,0 +1,68 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: compatlfs.h,v 1.5 2004/03/29 13:57:29 stelian Exp $ + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _COMPATLFS_H_ +#define _COMPATLFS_H_ + +#include + +#ifdef USE_LFS + +#define _LARGEFILE64_SOURCE +#define OPEN open64 +#define LSEEK lseek64 +#define STAT stat64 +#define LSTAT lstat64 +#define FTRUNCATE ftruncate64 +#define OFF_T __off64_t +#define MKSTEMP mkstemp64 +#define FTELL ftello64 + +#else + +#define OPEN open +#define LSEEK lseek +#define STAT stat +#define LSTAT lstat +#define FTRUNCATE ftruncate +#define OFF_T off_t +#define MKSTEMP mkstemp +#define FTELL ftell + +#endif /* USE_LFS */ + +#endif /* !_COMPATLFS_H_ */ diff --git a/compat/include/darwin.h b/compat/include/darwin.h new file mode 100644 index 0000000..bcab1ab --- /dev/null +++ b/compat/include/darwin.h @@ -0,0 +1,133 @@ +/* + * + */ + +#if defined(DUMP_MACOSX) + +#ifndef DARWIN_H +#define DARWIN_H + +#define INFOLEN 32 +#define CORRECT 2 + + +#define DARWIN_RSRC_NAME "/..namedfork/rsrc" +#define DARWIN_FINFO_NAME "/..namedfork/finfo" +/* + * some structs from the HFS+ info for OS X + * - including the header file causes messy clashes + */ + +struct FndrFileInfo { + u_int32_t fdType; /* file type */ + u_int32_t fdCreator; /* file creator */ + u_int16_t fdFlags; /* Finder flags */ + struct { + int16_t v; /* file's location */ + int16_t h; + } fdLocation; + int16_t opaque; +}; +typedef struct FndrFileInfo FndrFileInfo; + +struct FndrDirInfo { + struct { /* folder's window rectangle */ + int16_t top; + int16_t left; + int16_t bottom; + int16_t right; + } frRect; + unsigned short frFlags; /* Finder flags */ + struct { + u_int16_t v; /* folder's location */ + u_int16_t h; + } frLocation; + int16_t opaque; +}; +typedef struct FndrDirInfo FndrDirInfo; + + +struct FndrOpaqueInfo { + int8_t opaque[16]; +}; +typedef struct FndrOpaqueInfo FndrOpaqueInfo; + +struct fndrinfo_block_t { + FndrFileInfo finderInfo; + FndrOpaqueInfo extendedFinderInfo; +}; +typedef struct fndrinfo_block_t fndrinfo_block_t; + +struct attrinfo_block_t { + unsigned long info_length; + u_int32_t objid_low; + u_int32_t objid_high; + struct timespec created; + struct timespec backup; + union { + fndrinfo_block_t finfo; + FndrDirInfo dinfo; + } o; + off_t rsrc_length; +}; +typedef struct attrinfo_block_t attrinfo_block_t; + + +#define ASINGLE_MAGIC 0x00051600 /* all in one file */ +#define ADOUBLE_MAGIC 0x00051607 /* resource + info, data separated */ + +#define ASD_VERSION1 0x00010000 /* the original version */ +#define ASD_VERSION2 0x00020000 /* the second version */ + +typedef struct ASDHeader { + u_long magic; /* either single or double */ + u_long version; /* ASD_VERSION2 */ + u_char filler[16]; /* reserved, zero */ + u_short entries; /* the number of entries */ + /* the entries follow */ +} ASDHeader, *ASDHeaderPtr, **ASDHeaderHandle; + +typedef enum { + EntryDataFork = 1, + EntryRSRCFork, + EntryRealName, + EntryComment, + EntryBWIcon, + EntryColorIcon, + EntryOldFileInfo, + EntryFileDates, + EntryFinderInfo, + EntryMacFileInfo, + EntryProDOSInfo, + EntryMSDOSInfo, + EntryShortName, + EntryAFPFileInfo, + EntryDirID +} ASDEntryType; + +typedef struct { + u_long entryID; /* the entry type (forced to long) */ + u_long offset; /* offset in file of entry */ + u_long len; /* length of entry */ +} ASDEntry, *ASDEntryPtr, **ASDEntryHandle; + +typedef struct { + u_long creationDate; + u_long modificationDate; + u_long backupDate; + u_long accessDate; +} FileDates, *FileDatesPtr; + +typedef struct dumpfinderinfo { + FndrFileInfo fndrinfo; /* 0: size = 16 bytes, same for FndrDirInfo */ + u_int32_t createDate; /* 16: date and time of creation */ + u_int32_t contentModDate;/* 20: date/time of last content modification */ + u_int32_t attributeModDate;/* 24: date/time of last attribute modification */ + u_int32_t accessDate; /* 30: date/time of last access (MacOS X only) */ + u_int32_t backupDate; /* 34: date/time of last backup */ + u_int32_t textEncoding; /* 36: hint for name conversions */ + char filler[980]; /* 40: for later expansion, 40 + 980 - 4 = TP_BSIZE - 4 */ +} DumpFinderInfo, *DumpFinderInfoPtr; + +#endif /* DARWIN_H */ +#endif diff --git a/compat/include/lzoconf.h b/compat/include/lzoconf.h new file mode 100644 index 0000000..96db180 --- /dev/null +++ b/compat/include/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/compat/include/minilzo.h b/compat/include/minilzo.h new file mode 100644 index 0000000..e3270f9 --- /dev/null +++ b/compat/include/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/compat/include/pathnames.h b/compat/include/pathnames.h new file mode 100644 index 0000000..281d204 --- /dev/null +++ b/compat/include/pathnames.h @@ -0,0 +1,57 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: pathnames.h,v 1.14 2003/10/26 16:05:46 stelian Exp $ + */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#ifdef __linux__ +#include /* use the same default tape as "mt" */ +#define _PATH_DEFTAPE DEFTAPE +#endif + +#ifndef _PATH_DEFTAPE +#ifdef __linux__ +#define _PATH_DEFTAPE "/dev/st0" +#endif +#ifdef sunos +#define _PATH_DEFTAPE "/dev/rmt/0" +#endif +#endif + +#define _PATH_RMT "/etc/rmt" /* path on remote host */ diff --git a/compat/include/protocols/dumprestore.h b/compat/include/protocols/dumprestore.h new file mode 100644 index 0000000..fc43715 --- /dev/null +++ b/compat/include/protocols/dumprestore.h @@ -0,0 +1,175 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: dumprestore.h,v 1.22 2004/07/01 09:14:49 stelian Exp $ + */ + +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PROTOCOLS_DUMPRESTORE_H_ +#define _PROTOCOLS_DUMPRESTORE_H_ + +#include + +/* + * TP_BSIZE is the size of file blocks on the dump tapes. + * Note that TP_BSIZE must be a multiple of DEV_BSIZE. + * + * NTREC is the number of TP_BSIZE blocks that are written + * in each tape record. HIGHDENSITYTREC is the number of + * TP_BSIZE blocks that are written in each tape record on + * 6250 BPI or higher density tapes. + * + * TP_NINDIR is the number of indirect pointers in a TS_INODE + * or TS_ADDR record. Note that it must be a power of two. + */ +#define TP_BSIZE 1024 +#define NTREC 10 +#define HIGHDENSITYTREC 32 +#define TP_NINDIR (TP_BSIZE/2) +#define TP_NINOS (TP_NINDIR / sizeof (int32_t)) +#define LBLSIZE 16 +#define NAMELEN 64 + +#define OFS_MAGIC (int)60011 +#define NFS_MAGIC (int)60012 +#define FS_UFS2_MAGIC (int)0x19540119 +#define CHECKSUM (int)84446 + +#ifdef __linux__ +typedef u_int32_t dump_ino_t; +#endif + +#ifdef sunos +typedef unsigned int dump_ino_t; +#endif + +union u_data { + char s_addrs[TP_NINDIR]; /* 1 => data; 0 => hole in inode */ + int32_t s_inos[TP_NINOS]; /* table of first inode on each volume */ +} u_data; + +union u_spcl { + char dummy[TP_BSIZE]; + struct s_spcl { + int32_t c_type; /* record type (see below) */ + int32_t c_date; /* date of this dump */ + int32_t c_ddate; /* date of previous dump */ + int32_t c_volume; /* dump volume number */ + u_int32_t c_tapea; /* logical block of this record */ + dump_ino_t c_inumber; /* number of inode */ + int32_t c_magic; /* magic number (see above) */ + int32_t c_checksum; /* record checksum */ +#ifdef __linux__ + struct new_bsd_inode c_dinode; +#else +#ifdef sunos + struct new_bsd_inode c_dinode; +#else + struct dinode c_dinode; /* ownership and mode of inode */ +#endif +#endif + int32_t c_count; /* number of valid c_addr entries */ + union u_data c_data; /* see above */ + char c_label[LBLSIZE]; /* dump label */ + int32_t c_level; /* level of this dump */ + char c_filesys[NAMELEN]; /* name of dumpped file system */ + char c_dev[NAMELEN]; /* name of dumpped device */ + char c_host[NAMELEN]; /* name of dumpped host */ + int32_t c_flags; /* additional information */ + int32_t c_firstrec; /* first record on volume */ + int32_t c_ntrec; /* blocksize on volume */ + int32_t c_extattributes; /* additional inode info */ + int32_t c_spare[30]; /* reserved for future uses */ + } s_spcl; +} u_spcl; +#define spcl u_spcl.s_spcl +#define c_addr c_data.s_addrs +#define c_inos c_data.s_inos + +/* + * special record types + */ +#define TS_TAPE 1 /* dump tape header */ +#define TS_INODE 2 /* beginning of file record */ +#define TS_ADDR 4 /* continuation of file record */ +#define TS_BITS 3 /* map of inodes on tape */ +#define TS_CLRI 6 /* map of inodes deleted since last dump */ +#define TS_END 5 /* end of volume marker */ + +/* + * flag values + */ +#define DR_NEWHEADER 0x0001 /* new format tape header */ +#define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */ +#define DR_COMPRESSED 0x0080 /* dump tape is compressed */ +#define DR_METAONLY 0x0100 /* only the metadata of the inode has + been dumped */ +#define DR_INODEINFO 0x0002 /* TS_END header contains c_inos information */ +#define DR_EXTATTRIBUTES 0x8000 + +/* + * extattributes inode info + */ +#define EXT_REGULAR 0 +#define EXT_MACOSFNDRINFO 1 +#define EXT_MACOSRESFORK 2 +#define EXT_ACL 3 + + +/* + * compression flags for the tapebuf header. + */ +#define COMPRESS_ZLIB 0 +#define COMPRESS_BZLIB 1 +#define COMPRESS_LZO 2 + +/* used for compressed dump tapes */ +struct tapebuf { + unsigned int compressed:1; + unsigned int flags:3; + unsigned int length:28; +#ifdef sunos + char buf; +#else + char buf[0]; /* the data */ +#endif +}; + +#endif /* !_DUMPRESTORE_H_ */ diff --git a/compat/include/rmtflags.h b/compat/include/rmtflags.h new file mode 100644 index 0000000..a1c49fb --- /dev/null +++ b/compat/include/rmtflags.h @@ -0,0 +1,46 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: rmtflags.h,v 1.2 2003/03/30 15:40:34 stelian Exp $ + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _RMTFLAGS_H_ +#define _RMTFLAGS_H_ + +int rmtflags_toint(char *filemode); +char *rmtflags_tochar(int filemode); + +#endif diff --git a/compat/include/system.h b/compat/include/system.h new file mode 100644 index 0000000..5ed2d27 --- /dev/null +++ b/compat/include/system.h @@ -0,0 +1,45 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: system.h,v 1.3 2003/03/30 15:40:34 stelian Exp $ + */ + +#ifndef _SYSTEM_H_ +#define _SYSTEM_H_ + +int system_command(const char *command, const char *device, int volnum); + +#endif diff --git a/compat/lib/Makefile.in b/compat/lib/Makefile.in new file mode 100644 index 0000000..cc90969 --- /dev/null +++ b/compat/lib/Makefile.in @@ -0,0 +1,37 @@ +# $Id: Makefile.in,v 1.10 2003/05/08 21:11:39 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= ../.. + +@MCONFIG@ + +INC= -I$(top_srcdir)/compat/include +ALL_CFLAGS= @CPPFLAGS@ @CFLAGS@ @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) +SRCS= compaterr.c compatglob.c bylabel.c system.c rmtflags.c minilzo.c +OBJS= compaterr.o compatglob.o bylabel.o system.o rmtflags.o minilzo.o +LIB= libcompat.a + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +all:: $(LIB) + +$(LIB): $(OBJS) + $(AR) r $(LIB) $(OBJS) + $(RANLIB) $(LIB) + +install:: + +clean:: + $(RM) -f \#* *.s *.o *.a *~ core + +distclean:: clean + $(RM) -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/compat/lib/README.LZO b/compat/lib/README.LZO new file mode 100644 index 0000000..fd1ea8a --- /dev/null +++ b/compat/lib/README.LZO @@ -0,0 +1,133 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + + + ============================================================================ + miniLZO -- mini subset of the LZO real-time data compression library + ============================================================================ + + Author : Markus Franz Xaver Johannes Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + Version : 1.08 + Date : 12-Jul-2002 + + I've created miniLZO for projects where it is inconvenient to + include (or require) the full LZO source code just because you + want to add a little bit of data compression to your application. + + miniLZO implements the LZO1X-1 compressor and both the standard and + safe LZO1X decompressor. Apart from fast compression it also useful + for situations where you want to use pre-compressed data files (which + must have been compressed with LZO1X-999). + + miniLZO consists of one C source file and two header files: + minilzo.c + minilzo.h + lzoconf.h + + To use miniLZO just copy these files into your source directory, add + minilzo.c to your Makefile and #include minilzo.h from your program. + Note: you also must distribute this file (`README.LZO') with your project. + + minilzo.o compiles to about 6 kB (using gcc or Visual C on a i386), and + the sources are about 14 kB when packed with zip - so there's no more + excuse that your application doesn't support data compression :-) + + For more information, documentation, example programs and other support + files (like Makefiles and build scripts) please download the full LZO + package from + http://www.oberhumer.com/opensource/lzo/ + + Have fun, + Markus + + + P.S. minilzo.c is generated automatically from the LZO sources and + therefore functionality is completely identical + + + Appendix A: building miniLZO + ---------------------------- + miniLZO is written such a way that it should compile and run + out-of-the-box on most machines. + + If you are running on a very unusual architecture and lzo_init() fails then + you should first recompile with `-DLZO_DEBUG' to see what causes the failure. + The most probable case is something like `sizeof(char *) != sizeof(long)'. + After identifying the problem you can compile by adding some defines + like `-DSIZEOF_CHAR_P=8' to your Makefile. + + The best solution is (of course) using Autoconf - if your project uses + Autoconf anyway just add `-DMINILZO_HAVE_CONFIG_H' to your compiler + flags when compiling minilzo.c. See the LZO distribution for an example + how to set up configure.in. + + + Appendix B: list of public functions available in miniLZO + --------------------------------------------------------- + Library initialization + lzo_init() + + Compression + lzo1x_1_compress() + + Decompression + lzo1x_decompress() + lzo1x_decompress_safe() + + Checksum functions + lzo_adler32() + + Version functions + lzo_version() + lzo_version_string() + lzo_version_date() + + Portable (but slow) string functions + lzo_memcmp() + lzo_memcpy() + lzo_memmove() + lzo_memset() + + + Appendix C: suggested macros for `configure.in' when using Autoconf + ------------------------------------------------------------------- + Checks for typedefs and structures + AC_CHECK_TYPE(ptrdiff_t,long) + AC_TYPE_SIZE_T + AC_CHECK_SIZEOF(unsigned short) + AC_CHECK_SIZEOF(unsigned) + AC_CHECK_SIZEOF(unsigned long) + AC_CHECK_SIZEOF(char *) + AC_CHECK_SIZEOF(ptrdiff_t) + AC_CHECK_SIZEOF(size_t) + + Checks for compiler characteristics + AC_C_CONST + + Checks for library functions + AC_CHECK_FUNCS(memcmp memcpy memmove memset) + + + Appendix D: Copyright + --------------------- + LZO and miniLZO are Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Markus Franz Xaver Johannes Oberhumer + + LZO and miniLZO are distributed under the terms of the GNU General + Public License (GPL). See the file COPYING. + + Special licenses for commercial and other applications which + are not willing to accept the GNU General Public License + are available by contacting the author. + + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQE9LPb4TWFXqwsgQ8kRAi/wAKCZ9Iej+voGhmKATaViOPS9chxGUwCgh5Dk +uwMS2PQ7BXHT0vf4yz+3tTc= +=PsNp +-----END PGP SIGNATURE----- diff --git a/compat/lib/README2.LZO b/compat/lib/README2.LZO new file mode 100644 index 0000000..b27597c --- /dev/null +++ b/compat/lib/README2.LZO @@ -0,0 +1,10 @@ +The copyright notice in appendix D of the file README.LZO fully applies. + +Hereby I grant a special license to the "Dump/restore utilities" project +(currently hosted at http://dump.sourceforge.net ) to integrate the +minilzo project (currently version 1.08 hosted at +http://www.oberhumer.com/opensource/lzo) in source form. Both files, +README.LZO and README2.LZO, must be distributed with the source of the +"Dump/restore utilities". + +Markus Oberhumer, , http://www.oberhumer.com/ diff --git a/compat/lib/bylabel.c b/compat/lib/bylabel.c new file mode 100644 index 0000000..5a40a70 --- /dev/null +++ b/compat/lib/bylabel.c @@ -0,0 +1,261 @@ +/* + * mount_by_label.c - aeb + * + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * 2000-01-20 James Antill + * - Added error message if /proc/partitions cannot be opened + * 2000-05-09 Erik Troan + * - Added cache for UUID and disk labels + * Wed Aug 16 2000 Erik Troan + * - Ported to dump/restore + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bylabel.h" + +#ifndef HAVE_BLKID + +#define PROC_PARTITIONS "/proc/partitions" +#define DEVLABELDIR "/dev" + +#define EXT2_SUPER_OFFSET 1024 +#define EXT2_SUPER_SIZE sizeof(struct ext2_super_block) +#define EXT2_SUPER_MAGIC 0xEF53 + +#define VOLNAMSZ 16 + +struct ext2_super_block { + unsigned char s_dummy1[56]; + unsigned char s_magic[2]; + unsigned char s_dummy2[46]; + unsigned char s_uuid[16]; + unsigned char s_volume_name[VOLNAMSZ]; +}; +#define ext2magic(s) ((unsigned int) s.s_magic[0] + (((unsigned int) s.s_magic[1]) << 8)) + +void msg __P((const char *fmt, ...)); + +static struct uuidCache_s { + struct uuidCache_s *next; + char uuid[16]; + char *label; + char *device; +} *uuidCache = NULL; + +/* for now, only ext2 is supported */ +static int +get_label_uuid(const char *device, char **label, char *uuid) { + + /* start with a test for ext2, taken from mount_guess_fstype */ + /* should merge these later */ + int fd; + struct ext2_super_block e2sb; + + fd = OPEN(device, O_RDONLY); + if (fd < 0) + return 1; + + if (LSEEK(fd, EXT2_SUPER_OFFSET, SEEK_SET) != EXT2_SUPER_OFFSET || + read(fd, (char *) &e2sb, EXT2_SUPER_SIZE) != EXT2_SUPER_SIZE || + ext2magic(e2sb) != EXT2_SUPER_MAGIC) { + close(fd); + return 1; + } + + close(fd); + + /* superblock is ext2 - now what is its label? */ + memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); + *label = malloc(VOLNAMSZ + 1); + strncpy(*label, e2sb.s_volume_name, VOLNAMSZ); + (*label)[VOLNAMSZ] = 0; + + return 0; +} + +static void +uuidcache_addentry(char *device, char *label, char *uuid) { + struct uuidCache_s *last; + + if (!uuidCache) { + last = uuidCache = (struct uuidCache_s *)malloc(sizeof(*uuidCache)); + } else { + for (last = uuidCache; last->next; last = last->next) ; + last->next = (struct uuidCache_s *)malloc(sizeof(*uuidCache)); + last = last->next; + } + last->next = NULL; + last->device = device; + last->label = label; + memcpy(last->uuid, uuid, sizeof(last->uuid)); +} + +static void +uuidcache_init(void) { + char line[100]; + char *s; + int ma, mi, sz; + static char ptname[100]; + FILE *procpt; + char uuid[16], *label; + char device[110]; + int firstPass; + int handleOnFirst; + + if (uuidCache) + return; + + procpt = fopen(PROC_PARTITIONS, "r"); + if (!procpt) + return; + + for (firstPass = 1; firstPass >= 0; firstPass--) { + fseek(procpt, 0, SEEK_SET); + + while (fgets(line, sizeof(line), procpt)) { + if (sscanf (line, " %d %d %d %[^\n ]", + &ma, &mi, &sz, ptname) != 4) + continue; + + /* skip extended partitions (heuristic: size 1) */ + if (sz == 1) + continue; + + /* look only at md devices on first pass */ + handleOnFirst = !strncmp(ptname, "md", 2); + if (firstPass != handleOnFirst) + continue; + + /* skip entire disk (minor 0, 64, ... on ide; + 0, 16, ... on sd) */ + /* heuristic: partition name ends in a digit */ + + for(s = ptname; *s; s++); + if (isdigit(s[-1])) { + /* + * Note: this is a heuristic only - there is no reason + * why these devices should live in /dev. + * Perhaps this directory should be specifiable by option. + * One might for example have /devlabel with links to /dev + * for the devices that may be accessed in this way. + * (This is useful, if the cdrom on /dev/hdc must not + * be accessed.) + */ + sprintf(device, "%s/%s", DEVLABELDIR, ptname); + if (!get_label_uuid(device, &label, uuid)) + uuidcache_addentry(strdup(device), label, uuid); + } + } + } + + fclose(procpt); +} + +#define UUID 1 +#define VOL 2 + +static char * +get_spec_by_x(int n, const char *t) { + struct uuidCache_s *uc; + + uuidcache_init(); + uc = uuidCache; + + while(uc) { + switch (n) { + case UUID: + if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) + return strdup(uc->device); + break; + case VOL: + if (!strcmp(t, uc->label)) + return strdup(uc->device); + break; + } + uc = uc->next; + } + return NULL; +} + +static u_char +fromhex(char c) { + if (isdigit(c)) + return (c - '0'); + else if (islower(c)) + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} + +static char * +get_spec_by_uuid(const char *s) { + u_char uuid[16]; + int i; + + if (strlen(s) != 36 || + s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') + goto bad_uuid; + for (i=0; i<16; i++) { + if (*s == '-') s++; + if (!isxdigit(s[0]) || !isxdigit(s[1])) + goto bad_uuid; + uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1])); + s += 2; + } + return get_spec_by_x(UUID, uuid); + + bad_uuid: + msg("mount: bad UUID\n"); + return NULL; /* just for gcc */ +} + +static char * +get_spec_by_volume_label(const char *s) { + return get_spec_by_x(VOL, s); +} + +const char * +get_device_name(const char * item) { + const char * rc; + + if (!strncmp(item, "UUID=", 5)) { + rc = get_spec_by_uuid(item+5); + } + else + if (!strncmp(item, "LABEL=", 6)) { + rc = get_spec_by_volume_label(item+6); + } + else { + rc = item; + } + + return rc; +} + +const char * +get_device_label(const char * spec) { + struct uuidCache_s *uc; + + uuidcache_init(); + uc = uuidCache; + + while(uc) { + if (!strcmp(spec, uc->device)) + return uc->label[0] == '\0' ? NULL : strdup(uc->label); + uc = uc->next; + } + return NULL; +} + +#endif /* !HAVE_BLKID */ diff --git a/compat/lib/compaterr.c b/compat/lib/compaterr.c new file mode 100644 index 0000000..8ae4686 --- /dev/null +++ b/compat/lib/compaterr.c @@ -0,0 +1,223 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: compaterr.c,v 1.11 2003/10/26 16:05:46 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern char *__progname; /* Program name, from crt0. */ + +#if !defined(HAVE_ERR) || !defined(HAVE_ERRX) || !defined(HAVE_VERR) || !defined(HAVE_VERRX) || !defined(HAVE_VWARN) || !defined(HAVE_VWARNX) || !defined(HAVE_WARN) || !defined(HAVE_WARNX) + +__BEGIN_DECLS +__dead void errc __P((int, int, const char *, ...)); +__dead void verrc __P((int, int, const char *, _BSD_VA_LIST_)); +void warnc __P((int, const char *, ...)); +void vwarnc __P((int, const char *, _BSD_VA_LIST_)); +void err_set_file __P((void *)); +void err_set_exit __P((void (*)(int))); +__END_DECLS + +static void (*err_exit)(int); + +static FILE *err_file; /* file to use for error output */ +/* + * This is declared to take a `void *' so that the caller is not required + * to include first. However, it is really a `FILE *', and the + * manual page documents it as such. + */ +void +err_set_file(void *fp) +{ + if (fp) + err_file = fp; + else + err_file = stderr; +} + +void +err_set_exit(void (*ef)(int)) +{ + err_exit = ef; +} + +__dead void +errc(int eval, int code, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrc(eval, code, fmt, ap); + va_end(ap); +} + +__dead void +verrc(int eval, int code, const char *fmt, va_list ap) +{ + if (err_file == 0) + err_set_file((FILE *)0); + fprintf(err_file, "%s: ", __progname); + if (fmt != NULL) { + vfprintf(err_file, fmt, ap); + fprintf(err_file, ": "); + } + fprintf(err_file, "%s\n", strerror(code)); + if (err_exit) + err_exit(eval); + exit(eval); +} + +void +warnc(int code, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnc(code, fmt, ap); + va_end(ap); +} + +void +vwarnc(int code, const char *fmt, va_list ap) +{ + if (err_file == 0) + err_set_file((FILE *)0); + fprintf(err_file, "%s: ", __progname); + if (fmt != NULL) { + vfprintf(err_file, fmt, ap); + fprintf(err_file, ": "); + } + fprintf(err_file, "%s\n", strerror(code)); +} +#endif + +#ifndef HAVE_ERR +__dead void +err(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrc(eval, errno, fmt, ap); + va_end(ap); +} +#endif + +#ifndef HAVE_VERR +__dead void +verr(int eval, const char *fmt, va_list ap) +{ + verrc(eval, errno, fmt, ap); +} +#endif + +#ifndef HAVE_ERRX +__dead void +errx(int eval, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} +#endif + +#ifndef HAVE_VERRX +__dead void +verrx(int eval, const char *fmt, va_list ap) +{ + if (err_file == 0) + err_set_file((FILE *)0); + fprintf(err_file, "%s: ", __progname); + if (fmt != NULL) + vfprintf(err_file, fmt, ap); + fprintf(err_file, "\n"); + if (err_exit) + err_exit(eval); + exit(eval); +} +#endif + +#ifndef HAVE_WARN +void +warn(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnc(errno, fmt, ap); + va_end(ap); +} +#endif + +#ifndef HAVE_VWARN +void +vwarn(const char *fmt, va_list ap) +{ + vwarnc(errno, fmt, ap); +} +#endif + +#ifndef HAVE_WARNX +void +warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); +} +#endif + +#ifndef HAVE_VWARNX +void +vwarnx(const char *fmt, va_list ap) +{ + if (err_file == 0) + err_set_file((FILE *)0); + fprintf(err_file, "%s: ", __progname); + if (fmt != NULL) + vfprintf(err_file, fmt, ap); + fprintf(err_file, "\n"); +} +#endif diff --git a/compat/lib/compatglob.c b/compat/lib/compatglob.c new file mode 100644 index 0000000..8cf77ea --- /dev/null +++ b/compat/lib/compatglob.c @@ -0,0 +1,831 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * glob(3) -- a superset of the one defined in POSIX 1003.2. + * + * The [!...] convention to negate a range is supported (SysV, Posix, ksh). + * + * Optional extra services, controlled by flags not defined by POSIX: + * + * GLOB_QUOTE: + * Escaping convention: \ inhibits any special meaning the following + * character might have (except \ at end of string is retained). + * GLOB_MAGCHAR: + * Set in gl_flags if pattern contained a globbing character. + * GLOB_NOMAGIC: + * Same as GLOB_NOCHECK, but it will only append pattern if it did + * not contain any magic characters. [Used in csh style globbing] + * GLOB_ALTDIRFUNC: + * Use alternately specified directory access functions. + * GLOB_TILDE: + * expand ~user/foo to the /home/dir/of/user/foo + * GLOB_BRACE: + * expand {1,2}{a,b} to 1a 1b 2a 2b + * gl_matchc: + * Number of matches in the current invocation of glob. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: compatglob.c,v 1.10 2003/10/26 16:05:46 stelian Exp $"; +#endif /* not lint */ + +#include +#include + +#ifndef HAVE_GLOB + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DOLLAR '$' +#define DOT '.' +#define EOS '\0' +#define LBRACKET '[' +#define NOT '!' +#define QUESTION '?' +#define QUOTE '\\' +#define RANGE '-' +#define RBRACKET ']' +#define SEP '/' +#define STAR '*' +#define TILDE '~' +#define UNDERSCORE '_' +#define LBRACE '{' +#define RBRACE '}' +#define SLASH '/' +#define COMMA ',' + +#ifndef DEBUG + +#define M_QUOTE 0x8000 +#define M_PROTECT 0x4000 +#define M_MASK 0xffff +#define M_ASCII 0x00ff + +typedef u_short Char; + +#else + +#define M_QUOTE 0x80 +#define M_PROTECT 0x40 +#define M_MASK 0xff +#define M_ASCII 0x7f + +typedef char Char; + +#endif + + +#define CHAR(c) ((Char)((c)&M_ASCII)) +#define META(c) ((Char)((c)|M_QUOTE)) +#define M_ALL META('*') +#define M_END META(']') +#define M_NOT META('!') +#define M_ONE META('?') +#define M_RNG META('-') +#define M_SET META('[') +#define ismeta(c) (((c)&M_QUOTE) != 0) + + +static int compare __P((const void *, const void *)); +static void g_Ctoc __P((const Char *, char *)); +static int g_lstat __P((Char *, struct stat *, glob_t *)); +static DIR *g_opendir __P((Char *, glob_t *)); +static Char *g_strchr __P((Char *, int)); +#ifdef notdef +static Char *g_strcat __P((Char *, const Char *)); +#endif +static int g_stat __P((Char *, struct stat *, glob_t *)); +static int glob0 __P((const Char *, glob_t *)); +static int glob1 __P((Char *, glob_t *)); +static int glob2 __P((Char *, Char *, Char *, glob_t *)); +static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *)); +static int globextend __P((const Char *, glob_t *)); +static const Char * globtilde __P((const Char *, Char *, size_t, glob_t *)); +static int globexp1 __P((const Char *, glob_t *)); +static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); +static int match __P((Char *, Char *, Char *)); +#ifdef DEBUG +static void qprintf __P((const char *, Char *)); +#endif + +int +glob(const char *pattern, int flags, int (*errfunc) __P((const char *, int)), glob_t *pglob) +{ + const u_char *patnext; + int c; + Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; + + patnext = (u_char *) pattern; + if (!(flags & GLOB_APPEND)) { + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_offs = 0; + } + pglob->gl_flags = flags & ~GLOB_MAGCHAR; + pglob->gl_errfunc = errfunc; + pglob->gl_matchc = 0; + + bufnext = patbuf; + bufend = bufnext + MAXPATHLEN; + if (flags & GLOB_QUOTE) { + /* Protect the quoted characters. */ + while (bufnext < bufend && (c = *patnext++) != EOS) + if (c == QUOTE) { + if ((c = *patnext++) == EOS) { + c = QUOTE; + --patnext; + } + *bufnext++ = c | M_PROTECT; + } + else + *bufnext++ = c; + } + else + while (bufnext < bufend && (c = *patnext++) != EOS) + *bufnext++ = c; + *bufnext = EOS; + + if (flags & GLOB_BRACE) + return globexp1(patbuf, pglob); + else + return glob0(patbuf, pglob); +} + +/* + * Expand recursively a glob {} pattern. When there is no more expansion + * invoke the standard globbing routine to glob the rest of the magic + * characters + */ +static int globexp1(const Char *pattern, glob_t *pglob) +{ + const Char* ptr = pattern; + int rv; + + /* Protect a single {}, for find(1), like csh */ + if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) + return glob0(pattern, pglob); + + while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + if (!globexp2(ptr, pattern, pglob, &rv)) + return rv; + + return glob0(pattern, pglob); +} + + +/* + * Recursive brace globbing helper. Tries to expand a single brace. + * If it succeeds then it invokes globexp1 with the new pattern. + * If it fails then it tries to glob the rest of the pattern and returns. + */ +static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) +{ + int i; + Char *lm, *ls; + const Char *pe, *pm, *pl; + Char patbuf[MAXPATHLEN + 1]; + + /* copy part up to the brace */ + for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) + continue; + ls = lm; + + /* Find the balanced brace */ + for (i = 0, pe = ++ptr; *pe; pe++) + if (*pe == LBRACKET) { + /* Ignore everything between [] */ + for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) + continue; + if (*pe == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pe = pm; + } + } + else if (*pe == LBRACE) + i++; + else if (*pe == RBRACE) { + if (i == 0) + break; + i--; + } + + /* Non matching braces; just glob the pattern */ + if (i != 0 || *pe == EOS) { + *rv = glob0(patbuf, pglob); + return 0; + } + + for (i = 0, pl = pm = ptr; pm <= pe; pm++) + switch (*pm) { + case LBRACKET: + /* Ignore everything between [] */ + for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) + continue; + if (*pm == EOS) { + /* + * We could not find a matching RBRACKET. + * Ignore and just look for RBRACE + */ + pm = pl; + } + break; + + case LBRACE: + i++; + break; + + case RBRACE: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ + case COMMA: + if (i && *pm == COMMA) + break; + else { + /* Append the current string */ + for (lm = ls; (pl < pm); *lm++ = *pl++) + continue; + /* + * Append the rest of the pattern after the + * closing brace + */ + for (pl = pe + 1; (*lm++ = *pl++) != EOS;) + continue; + + /* Expand the current pattern */ +#ifdef DEBUG + qprintf("globexp2:", patbuf); +#endif + *rv = globexp1(patbuf, pglob); + + /* move after the comma, to the next string */ + pl = pm + 1; + } + break; + + default: + break; + } + *rv = 0; + return 0; +} + + + +/* + * expand tilde from the passwd file. + */ +static const Char * +globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) +{ + struct passwd *pwd; + char *h; + const Char *p; + Char *b, *eb; + + if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) + return pattern; + + /* + * Copy up to the end of the string or / + */ + eb = &patbuf[patbuf_len - 1]; + for (p = pattern + 1, h = (char *) patbuf; + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) + continue; + + *h = EOS; + + if (((char *) patbuf)[0] == EOS) { + /* + * handle a plain ~ or ~/ by expanding $HOME first if + * we're not running setuid or setgid) and then trying + * the password file + */ + if ( +#if !defined(__linux__) && !defined(sunos) +#ifndef __NETBSD_SYSCALLS + issetugid() != 0 || +#endif +#endif + (h = getenv("HOME")) == NULL) { + if (((h = getlogin()) != NULL && + (pwd = getpwnam(h)) != NULL) || + (pwd = getpwuid(getuid())) != NULL) + h = pwd->pw_dir; + else + return pattern; + } + } + else { + /* + * Expand a ~user + */ + if ((pwd = getpwnam((char*) patbuf)) == NULL) + return pattern; + else + h = pwd->pw_dir; + } + + /* Copy the home directory */ + for (b = patbuf; b < eb && *h; *b++ = *h++) + continue; + + /* Append the rest of the pattern */ + while (b < eb && (*b++ = *p++) != EOS) + continue; + *b = EOS; + + return patbuf; +} + + +/* + * The main glob() routine: compiles the pattern (optionally processing + * quotes), calls glob1() to do the real pattern matching, and finally + * sorts the list (unless unsorted operation is requested). Returns 0 + * if things went well, nonzero if errors occurred. It is not an error + * to find no matches. + */ +static int +glob0(const Char *pattern, glob_t *pglob) +{ + const Char *qpatnext; + int c, err, oldpathc; + Char *bufnext, patbuf[MAXPATHLEN+1]; + + qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char), + pglob); + oldpathc = pglob->gl_pathc; + bufnext = patbuf; + + /* We don't need to check for buffer overflow any more. */ + while ((c = *qpatnext++) != EOS) { + switch (c) { + case LBRACKET: + c = *qpatnext; + if (c == NOT) + ++qpatnext; + if (*qpatnext == EOS || + g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + *bufnext++ = LBRACKET; + if (c == NOT) + --qpatnext; + break; + } + *bufnext++ = M_SET; + if (c == NOT) + *bufnext++ = M_NOT; + c = *qpatnext++; + do { + *bufnext++ = CHAR(c); + if (*qpatnext == RANGE && + (c = qpatnext[1]) != RBRACKET) { + *bufnext++ = M_RNG; + *bufnext++ = CHAR(c); + qpatnext += 2; + } + } while ((c = *qpatnext++) != RBRACKET); + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_END; + break; + case QUESTION: + pglob->gl_flags |= GLOB_MAGCHAR; + *bufnext++ = M_ONE; + break; + case STAR: + pglob->gl_flags |= GLOB_MAGCHAR; + /* collapse adjacent stars to one, + * to avoid exponential behavior + */ + if (bufnext == patbuf || bufnext[-1] != M_ALL) + *bufnext++ = M_ALL; + break; + default: + *bufnext++ = CHAR(c); + break; + } + } + *bufnext = EOS; +#ifdef DEBUG + qprintf("glob0:", patbuf); +#endif + + if ((err = glob1(patbuf, pglob)) != 0) + return(err); + + /* + * If there was no match we are going to append the pattern + * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified + * and the pattern did not contain any magic characters + * GLOB_NOMAGIC is there just for compatibility with csh. + */ + if (pglob->gl_pathc == oldpathc && + ((pglob->gl_flags & GLOB_NOCHECK) || + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR)))) + return(globextend(pattern, pglob)); + else if (!(pglob->gl_flags & GLOB_NOSORT)) + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), compare); + return(0); +} + +static int +compare(const void *p, const void *q) +{ + return(strcmp(*(char **)p, *(char **)q)); +} + +static int +glob1(Char *pattern, glob_t *pglob) +{ + Char pathbuf[MAXPATHLEN+1]; + + /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ + if (*pattern == EOS) + return(0); + return(glob2(pathbuf, pathbuf, pattern, pglob)); +} + +/* + * The functions glob2 and glob3 are mutually recursive; there is one level + * of recursion for each segment in the pattern that contains one or more + * meta characters. + */ +static int +glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob) +{ + struct stat sb; + Char *p, *q; + int anymeta; + + /* + * Loop over pattern segments until end of pattern or until + * segment with meta character found. + */ + for (anymeta = 0;;) { + if (*pattern == EOS) { /* End of pattern? */ + *pathend = EOS; + if (g_lstat(pathbuf, &sb, pglob)) + return(0); + + if (((pglob->gl_flags & GLOB_MARK) && + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) + || (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { + *pathend++ = SEP; + *pathend = EOS; + } + ++pglob->gl_matchc; + return(globextend(pathbuf, pglob)); + } + + /* Find end of next segment, copy tentatively to pathend. */ + q = pathend; + p = pattern; + while (*p != EOS && *p != SEP) { + if (ismeta(*p)) + anymeta = 1; + *q++ = *p++; + } + + if (!anymeta) { /* No expansion, do next segment. */ + pathend = q; + pattern = p; + while (*pattern == SEP) + *pathend++ = *pattern++; + } else /* Need expansion, recurse. */ + return(glob3(pathbuf, pathend, pattern, p, pglob)); + } + /* NOTREACHED */ +} + +static int +glob3(Char *pathbuf, Char *pathend, Char *pattern, Char *restpattern, glob_t *pglob) +{ + struct dirent *dp; + DIR *dirp; + int err; + char buf[MAXPATHLEN]; + + /* + * The readdirfunc declaration can't be prototyped, because it is + * assigned, below, to two functions which are prototyped in glob.h + * and dirent.h as taking pointers to differently typed opaque + * structures. + */ + struct dirent *(*readdirfunc)(); + + *pathend = EOS; + errno = 0; + + if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { + /* TODO: don't call for ENOENT or ENOTDIR? */ + if (pglob->gl_errfunc) { + g_Ctoc(pathbuf, buf); + if (pglob->gl_errfunc(buf, errno) || + pglob->gl_flags & GLOB_ERR) + return (GLOB_ABEND); + } + return(0); + } + + err = 0; + + /* Search directory for matching names. */ + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + readdirfunc = pglob->gl_readdir; + else + readdirfunc = readdir; + while ((dp = (*readdirfunc)(dirp))) { + u_char *sc; + Char *dc; + + /* Initial DOT must be matched literally. */ + if (dp->d_name[0] == DOT && *pattern != DOT) + continue; + for (sc = (u_char *) dp->d_name, dc = pathend; + (*dc++ = *sc++) != EOS;) + continue; + if (!match(pathend, pattern, restpattern)) { + *pathend = EOS; + continue; + } + err = glob2(pathbuf, --dc, restpattern, pglob); + if (err) + break; + } + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir)(dirp); + else + closedir(dirp); + return(err); +} + + +/* + * Extend the gl_pathv member of a glob_t structure to accomodate a new item, + * add the new item, and update gl_pathc. + * + * This assumes the BSD realloc, which only copies the block when its size + * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic + * behavior. + * + * Return 0 if new item added, error code if memory couldn't be allocated. + * + * Invariant of the glob_t structure: + * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and + * gl_pathv points to (gl_offs + gl_pathc + 1) items. + */ +static int +globextend(const Char *path, glob_t *pglob) +{ + char **pathv; + int i; + u_int newsize; + char *copy; + const Char *p; + + newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); + pathv = pglob->gl_pathv ? + realloc((char *)pglob->gl_pathv, newsize) : + malloc(newsize); + if (pathv == NULL) + return(GLOB_NOSPACE); + + if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + pathv += pglob->gl_offs; + for (i = pglob->gl_offs; --i >= 0; ) + *--pathv = NULL; + } + pglob->gl_pathv = pathv; + + for (p = path; *p++;) + continue; + if ((copy = malloc(p - path)) != NULL) { + g_Ctoc(path, copy); + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + } + pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + return(copy == NULL ? GLOB_NOSPACE : 0); +} + +/* + * pattern matching function for filenames. Each occurrence of the * + * pattern causes a recursion level. + */ +static int +match(Char *name, Char *pat, Char *patend) +{ + int ok, negate_range; + Char c, k; + + while (pat < patend) { + c = *pat++; + switch (c & M_MASK) { + case M_ALL: + if (pat == patend) + return(1); + do + if (match(name, pat, patend)) + return(1); + while (*name++ != EOS); + return(0); + case M_ONE: + if (*name++ == EOS) + return(0); + break; + case M_SET: + ok = 0; + if ((k = *name++) == EOS) + return(0); + if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) + ++pat; + while (((c = *pat++) & M_MASK) != M_END) + if ((*pat & M_MASK) == M_RNG) { + if (c <= k && k <= pat[1]) + ok = 1; + pat += 2; + } else if (c == k) + ok = 1; + if (ok == negate_range) + return(0); + break; + default: + if (*name++ != c) + return(0); + break; + } + } + return(*name == EOS); +} + +/* Free allocated data belonging to a glob_t structure. */ +void +globfree(glob_t *pglob) +{ + int i; + char **pp; + + if (pglob->gl_pathv != NULL) { + pp = pglob->gl_pathv + pglob->gl_offs; + for (i = pglob->gl_pathc; i--; ++pp) + if (*pp) + free(*pp); + free(pglob->gl_pathv); + } +} + +static DIR * +g_opendir(Char *str, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + if (!*str) + strcpy(buf, "."); + else + g_Ctoc(str, buf); + + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_opendir)(buf)); + + return(opendir(buf)); +} + +static int +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_lstat)(buf, sb)); + return(lstat(buf, sb)); +} + +static int +g_stat(Char *fn, struct stat *sb, glob_t *pglob) +{ + char buf[MAXPATHLEN]; + + g_Ctoc(fn, buf); + if (pglob->gl_flags & GLOB_ALTDIRFUNC) + return((*pglob->gl_stat)(buf, sb)); + return(stat(buf, sb)); +} + +static Char * +g_strchr(Char *str, int ch) +{ + do { + if (*str == ch) + return (str); + } while (*str++); + return (NULL); +} + +#ifdef notdef +static Char * +g_strcat(Char *dst, const Char *src) +{ + Char *sdst = dst; + + while (*dst++) + continue; + --dst; + while((*dst++ = *src++) != EOS) + continue; + + return (sdst); +} +#endif + +static void +g_Ctoc(const Char *str, char *buf) +{ + char *dc; + + for (dc = buf; (*dc++ = *str++) != EOS;) + continue; +} + +#ifdef DEBUG +static void +qprintf(const char *str, Char *s) +{ + Char *p; + + (void)printf("%s:\n", str); + for (p = s; *p; p++) + (void)printf("%c", CHAR(*p)); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", *p & M_PROTECT ? '"' : ' '); + (void)printf("\n"); + for (p = s; *p; p++) + (void)printf("%c", ismeta(*p) ? '_' : ' '); + (void)printf("\n"); +} +#endif + +#endif /* ! HAVE_GLOB */ diff --git a/compat/lib/minilzo.c b/compat/lib/minilzo.c new file mode 100644 index 0000000..85771eb --- /dev/null +++ b/compat/lib/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/compat/lib/rmtflags.c b/compat/lib/rmtflags.c new file mode 100644 index 0000000..5181f1c --- /dev/null +++ b/compat/lib/rmtflags.c @@ -0,0 +1,188 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: rmtflags.c,v 1.3 2003/03/30 15:40:35 stelian Exp $"; +#endif /* not linux */ + +/* + * rmt + */ +#include +#include +#include +#include +#include +#include +#include + +struct openflags { + char *name; + int value; +} openflags[] = { + { "O_RDONLY", O_RDONLY }, + { "O_WRONLY", O_WRONLY }, + { "O_RDWR", O_RDWR }, +#ifdef O_CREAT + { "O_CREAT", O_CREAT }, +#endif +#ifdef O_EXCL + { "O_EXCL", O_EXCL }, +#endif +#ifdef O_NOCTTY + { "O_NOCTTY", O_NOCTTY }, +#endif +#ifdef O_TRUNC + { "O_TRUNC", O_TRUNC }, +#endif +#ifdef O_APPEND + { "O_APPEND", O_APPEND }, +#endif +#ifdef O_NONBLOCK + { "O_NONBLOCK", O_NONBLOCK }, +#endif +#ifdef O_NDELAY + { "O_NDELAY", O_NDELAY }, +#endif +#ifdef O_SYNC + { "O_SYNC", O_SYNC }, +#endif +#ifdef O_FSYNC + { "O_FSYNC", O_FSYNC }, +#endif +#ifdef O_ASYNC + { "O_ASYNC", O_ASYNC }, +#endif +#ifdef O_TEXT + { "O_TEXT", O_TEXT }, +#endif +#ifdef O_DSYNC + { "O_DSYNC", O_DSYNC }, +#endif +#ifdef O_RSYNC + { "O_RSYNC", O_RSYNC }, +#endif +#ifdef O_PRIV + { "O_PRIV", O_PRIV }, +#endif +#ifdef O_LARGEFILE + { "O_LARGEFILE",O_LARGEFILE }, +#endif + { NULL, 0 } +}; + +/* Parts of this stolen again from Jörg Schilling's star package... */ +int +rmtflags_toint(char *filemode) +{ + char *p = filemode; + struct openflags *op; + int result = 0; + int numresult = 0; + int seentext = 0; + + do { + /* skip space */ + while (*p != '\0' && *p == ' ') + p++; + /* get O_XXXX constant */ + if (p[0] != 'O' || p[1] != '_') { + /* numeric syntax detected */ + numresult = atoi(filemode); + numresult &= O_RDONLY | O_WRONLY | O_RDWR; + while (*p != ' ' && *p != '\0') + p++; + while (*p != '\0' && *p == ' ') + p++; + } + + if (*p == '\0') + break; + + /* translate O_XXXX constant */ + for (op = openflags; op->name; op++) { + int slen = strlen(op->name); + if ((strncmp(op->name, p, slen) == 0) && + (p[slen] == '|' || p[slen] == ' ' || + p[slen] == '\0')) { + seentext = 1; + result |= op->value; + break; + } + } + + /* goto next constant */ + p = strchr(p, '|'); + } while (p && *p++ == '|'); + + if (!seentext) + result = numresult; + return result; +} + +char * +rmtflags_tochar(int filemode) +{ + struct openflags *op; + char *result = (char *) malloc(4096); /* enough space */ + + switch (filemode & O_ACCMODE) { + case O_RDONLY: + strcpy(result, "O_RDONLY"); + break; + case O_WRONLY: + strcpy(result, "O_WRONLY"); + break; + case O_RDWR: + strcpy(result, "O_RDWR"); + break; + default: + strcat(result, "ERROR"); + } + for (op = openflags; op->name; op++) { + if (op->value == O_RDONLY || + op->value == O_WRONLY || + op->value == O_RDWR) + continue; + if (filemode & op->value) { + strcat(result, "|"); + strcat(result, op->name); + } + } + return result; +} diff --git a/compat/lib/system.c b/compat/lib/system.c new file mode 100644 index 0000000..b3b7932 --- /dev/null +++ b/compat/lib/system.c @@ -0,0 +1,94 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: system.c,v 1.4 2003/03/30 15:40:35 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "system.h" + +/* + * Executes the command in a shell. + * Returns -1 if an error occured, the exit status of + * the command on success. + */ +int system_command(const char *command, const char *device, int volnum) { + int pid, status; + char commandstr[4096]; + + pid = fork(); + if (pid == -1) { + perror(" DUMP: unable to fork"); + return -1; + } + if (pid == 0) { + setuid(getuid()); + setgid(getgid()); +#if OLD_STYLE_FSCRIPT + snprintf(commandstr, sizeof(commandstr), "%s", command); +#else + snprintf(commandstr, sizeof(commandstr), "%s %s %d", command, device, volnum); +#endif + commandstr[sizeof(commandstr) - 1] = '\0'; + execl("/bin/sh", "sh", "-c", commandstr, NULL); + perror("unable to execute shell"); + exit(-1); + } + do { + if (waitpid(pid, &status, 0) == -1) { + if (errno != EINTR) { + perror("waitpid error"); + return -1; + } + } else { + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else + return -1; + } + } while(1); +} + diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..fd30ab0 --- /dev/null +++ b/config.guess @@ -0,0 +1,1354 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-07-23' + +# This file 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# This shell variable is my proudest work .. or something. --bje + +set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; +(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) + || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; +dummy=$tmpdir/dummy ; +files="$dummy.c $dummy.o $dummy.rel $dummy" ; +trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $files ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; +unset files' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + eval $set_cc_for_build + cat <$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + 3-1307) + UNAME_MACHINE="alphaev7" + ;; + esac + fi + rm -f $dummy.s $dummy && rmdir $tmpdir + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy && rmdir $tmpdir + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c && rmdir $tmpdir + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 +rm -f $dummy.c $dummy && rmdir $tmpdir + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..799b2f0 --- /dev/null +++ b/config.h.in @@ -0,0 +1,129 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define this if you want to include Quick File Access debugging code. */ +#undef DEBUG_QFA + +/* Define this if you want to include Mac OSX restore compatibility. */ +#undef DUMP_MACOSX + +/* Define this if you have the blkid library. */ +#undef HAVE_BLKID + +/* Define this if you have bzlib compression library. */ +#undef HAVE_BZLIB + +/* Define to 1 if you have the `err' function. */ +#undef HAVE_ERR + +/* Define to 1 if you have the `errx' function. */ +#undef HAVE_ERRX + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXT2FS_EXT2_FS_H + +/* Define if we have the ext2_ino_t type (from e2fsprogs 1.20+). */ +#undef HAVE_EXT2_INO_T + +/* Define if we have the s_journal_inum field in struct ext2_super_block. */ +#undef HAVE_EXT2_JOURNAL_INUM + +/* Define if you have the glob function. */ +#undef HAVE_GLOB + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `lchown' function. */ +#undef HAVE_LCHOWN + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you want to include readline support. */ +#undef HAVE_READLINE + +/* Define this if your readline libs have the rl_completion_append_character + variable. */ +#undef HAVE_READLINE_CAC + +/* Define this if your readline libs have the rl_completion_matches library. + */ +#undef HAVE_READLINE_RLCM + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `verr' function. */ +#undef HAVE_VERR + +/* Define to 1 if you have the `verrx' function. */ +#undef HAVE_VERRX + +/* Define to 1 if you have the `vwarn' function. */ +#undef HAVE_VWARN + +/* Define to 1 if you have the `vwarnx' function. */ +#undef HAVE_VWARNX + +/* Define to 1 if you have the `warn' function. */ +#undef HAVE_WARN + +/* Define to 1 if you have the `warnx' function. */ +#undef HAVE_WARNX + +/* Define this if you have zlib compression library. */ +#undef HAVE_ZLIB + +/* Define this is you want old style F script (no arguments). */ +#undef OLD_STYLE_FSCRIPT + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define this if you want Large File System support. */ +#undef USE_LFS + +/* Define this if you want Quick File Access support. */ +#undef USE_QFA + +/* Define to `int64_t' if does not define. */ +#undef quad_t + +/* Define to `uint64_t' if does not define. */ +#undef u_quad_t diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..9ff085e --- /dev/null +++ b/config.sub @@ -0,0 +1,1460 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-07-03' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipstx39 | mipstx39el \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..0fb7c6d --- /dev/null +++ b/configure @@ -0,0 +1,6638 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="dump/dump.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS SET_MAKE LN_S CP MV RM AR ac_ct_AR RANLIB ac_ct_RANLIB PATCH ac_ct_PATCH CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP DUMPDEBUG RESTOREDEBUG STATIC RMTDIR ERMT CRYPTO OPTDEFS READLINE LD CCOPTS LDOPTS BINOWNER BINGRP BINMODE MANOWNER MANGRP MANMODE DUMPDATESPATH BLKID ZLIB BZLIB top_builddir LIBOBJS LTLIBOBJS' +ac_subst_files='MCONFIG' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug include debugging code (default is NO) + --enable-static link dump and restore statically (default is NO) + --enable-staticz link libz and libbz2 statically (default is NO) + --enable-rmt compile and install rmt (default is YES) + --enable-ermt compile ermt, an encrypting version of rmt (default is NO) + --enable-kerberos compile kerberos extensions (default is NO) + --enable-readline enable readline support in restore (default is YES) + --enable-oldstylefscript enable old style F script (no arguments) (default is NO) + --enable-largefile enable Large File System support (default is YES) + --enable-qfa enable Quick File Access support (default is YES) + --enable-qfadebug include Quick File Access debugging code (default is NO) + --enable-macosx include Mac OSX restore compatibility (default is NO) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-cc=COMPILER select compiler to use + --with-linker=LINKER select linker to use + --with-ccopts=CCOPTS select compiler command line options + --with-ldopts=LDOPTS select linker command line options + --with-binowner=USER select owner for binaries + --with-bingrp=GROUP select group for binaries + --with-binmode=MODE select mode for binaries + --with-manowner=USER select owner for manual pages + --with-mangrp=GROUP select group for manual pages + --with-manmode=MODE select mode for manual pages + --with-dumpdatespath=PATH select path for dumpdates file + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + + + +MCONFIG=./MCONFIG + + + ac_config_headers="$ac_config_headers config.h" + + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_CP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_CP" && ac_cv_path_CP="cp" + ;; +esac +fi +CP=$ac_cv_path_CP + +if test -n "$CP"; then + echo "$as_me:$LINENO: result: $CP" >&5 +echo "${ECHO_T}$CP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MV in + [\\/]* | ?:[\\/]*) + ac_cv_path_MV="$MV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_MV" && ac_cv_path_MV="mv" + ;; +esac +fi +MV=$ac_cv_path_MV + +if test -n "$MV"; then + echo "$as_me:$LINENO: result: $MV" >&5 +echo "${ECHO_T}$MV" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_RM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RM in + [\\/]* | ?:[\\/]*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" + ;; +esac +fi +RM=$ac_cv_path_RM + +if test -n "$RM"; then + echo "$as_me:$LINENO: result: $RM" >&5 +echo "${ECHO_T}$RM" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="ar" +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + AR=$ac_ct_AR +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}patch", so it can be a program name with args. +set dummy ${ac_tool_prefix}patch; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_PATCH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$PATCH"; then + ac_cv_prog_PATCH="$PATCH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PATCH="${ac_tool_prefix}patch" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +PATCH=$ac_cv_prog_PATCH +if test -n "$PATCH"; then + echo "$as_me:$LINENO: result: $PATCH" >&5 +echo "${ECHO_T}$PATCH" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_PATCH"; then + ac_ct_PATCH=$PATCH + # Extract the first word of "patch", so it can be a program name with args. +set dummy patch; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_PATCH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_PATCH"; then + ac_cv_prog_ac_ct_PATCH="$ac_ct_PATCH" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_PATCH="patch" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_PATCH" && ac_cv_prog_ac_ct_PATCH=":" +fi +fi +ac_ct_PATCH=$ac_cv_prog_ac_ct_PATCH +if test -n "$ac_ct_PATCH"; then + echo "$as_me:$LINENO: result: $ac_ct_PATCH" >&5 +echo "${ECHO_T}$ac_ct_PATCH" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + PATCH=$ac_ct_PATCH +else + PATCH="$ac_cv_prog_PATCH" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in sys/types.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +CPPFLAGS="-D_BSD_SOURCE -D_USE_BSD_SIGNAL ${CPPFLAGS}" + +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + if test "$enableval" = "no" +then + DUMPDEBUG="" + RESTOREDEBUG="" + echo "Not including debugging code" +else + DUMPDEBUG="-DFDEBUG -DTDEBUG -DWRITEDEBUG -DDIRDEBUG" + RESTOREDEBUG="-DDIRDEBUG" + echo "Including debugging code" +fi +else + DUMPDEBUG="" +RESTOREDEBUG="" +echo "Not including debugging code by default" + +fi; + + + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + if test "$enableval" = "no" +then + STATIC="" + echo "Linking dump and restore dynamically" +else + STATIC="-static" + echo "Linking dump and restore statically" +fi + +else + STATIC="" +echo "Linking dump and restore dynamically by default" + +fi; + + +# Check whether --enable-staticz or --disable-staticz was given. +if test "${enable_staticz+set}" = set; then + enableval="$enable_staticz" + if test "$enableval" = "no" +then + STATICZ="no" + echo "Linking libz and libbz2 dynamically" +else + STATICZ="yes" + echo "Linking libz and libbz2 statically" +fi + +else + STATICZ="no" +echo "Linking libz and libbz2 dynamically by default" + +fi; + +# Check whether --enable-rmt or --disable-rmt was given. +if test "${enable_rmt+set}" = set; then + enableval="$enable_rmt" + if test "$enableval" = "no" +then + RMTDIR="" + RMTMAKEFILE="" + echo "Not compiling rmt" +else + RMTDIR="rmt" + RMTMAKEFILE="rmt/Makefile" + echo "Compiling rmt" +fi + +else + RMTDIR="rmt" +RMTMAKEFILE="rmt/Makefile" +echo "Compiling rmt by default" + +fi; + + +# Check whether --enable-ermt or --disable-ermt was given. +if test "${enable_ermt+set}" = set; then + enableval="$enable_ermt" + if test "$enableval" = "no" +then + ERMT="" + CRYPTO="" + echo "Not compiling ermt" +else + if test "$RMTDIR" = "" + then + { { echo "$as_me:$LINENO: error: ermt requires --enable-rmt" >&5 +echo "$as_me: error: ermt requires --enable-rmt" >&2;} + { (exit 1); exit 1; }; } + fi + ERMT="ermt" + CRYPTO="-lcrypto" + echo "Compiling ermt" +fi + +else + ERMT="" +CRYPTO="" +echo "Not compiling ermt by default" + +fi; + + + +# Check whether --enable-kerberos or --disable-kerberos was given. +if test "${enable_kerberos+set}" = set; then + enableval="$enable_kerberos" + if test "$enableval" = "yes" +then + OPTDEFS="-DKERBEROS" + echo "Compiling kerberos extensions" +else + OPTDEFS="" + echo "Not compiling kerberos extensions" +fi + +else + OPTDEFS="" +echo "Not compiling kerberos extensions by default" + +fi; + + +# Check whether --enable-readline or --disable-readline was given. +if test "${enable_readline+set}" = set; then + enableval="$enable_readline" + if test "$enableval" = "no" +then + READLINE="" + echo "Not including readline support" +else + READLINE="-lreadline -ltermcap" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_READLINE 1 +_ACEOF + + echo "Including readline support" +fi + +else + READLINE="-lreadline -ltermcap" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_READLINE 1 +_ACEOF + +echo "Including readline support by default" + +fi; + + +# Check whether --enable-oldstylefscript or --disable-oldstylefscript was given. +if test "${enable_oldstylefscript+set}" = set; then + enableval="$enable_oldstylefscript" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define OLD_STYLE_FSCRIPT 1 +_ACEOF + + echo "Using old style F script" +else + echo "Using new style F script" +fi + +else + echo "Using new style F script by default" + +fi; + +# Check whether --enable-largefile or --disable-largefile was given. +if test "${enable_largefile+set}" = set; then + enableval="$enable_largefile" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define USE_LFS 1 +_ACEOF + + echo "Enabling Large File System support" +else + echo "Not enabling Large File System support" +fi + +else + +cat >>confdefs.h <<\_ACEOF +#define USE_LFS 1 +_ACEOF + +echo "Enabling Large File System support by default" + +fi; + +# Check whether --enable-qfa or --disable-qfa was given. +if test "${enable_qfa+set}" = set; then + enableval="$enable_qfa" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define USE_QFA 1 +_ACEOF + + echo "Enabling Quick File Access support" +else + echo "Not enabling Quick File Access support" +fi + +else + +cat >>confdefs.h <<\_ACEOF +#define USE_QFA 1 +_ACEOF + +echo "Enabling Quick File Access support by default" + +fi; + +# Check whether --enable-qfadebug or --disable-qfadebug was given. +if test "${enable_qfadebug+set}" = set; then + enableval="$enable_qfadebug" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define DEBUG_QFA 1 +_ACEOF + + echo "Including Quick File Access debugging code" +else + echo "Not including Quick File Access debugging code" +fi + +else + echo "Not including Quick File Access debugging code by default" + +fi; + +# Check whether --enable-macosx or --disable-macosx was given. +if test "${enable_macosx+set}" = set; then + enableval="$enable_macosx" + if test "$enableval" = "yes" +then + +cat >>confdefs.h <<\_ACEOF +#define DUMP_MACOSX 1 +_ACEOF + + echo "Including Mac OSX restore compatibility code" +else + echo "Not including Mac OSX restore compatibility code" +fi + +else + echo "Not including Mac OSX restore compatibility code by default" + +fi; + + + +# Check whether --with-cc or --without-cc was given. +if test "${with_cc+set}" = set; then + withval="$with_cc" + echo "$as_me:$LINENO: result: CC=$withval" >&5 +echo "${ECHO_T}CC=$withval" >&6 +CC=$withval +else + if test -z "$CC" ; then CC=cc; fi +echo "$as_me:$LINENO: result: CC defaults to $CC" >&5 +echo "${ECHO_T}CC defaults to $CC" >&6 +fi; export CC + + + +# Check whether --with-linker or --without-linker was given. +if test "${with_linker+set}" = set; then + withval="$with_linker" + echo "$as_me:$LINENO: result: LD=$withval" >&5 +echo "${ECHO_T}LD=$withval" >&6 +LD=$withval +else + if test -z "$LD" ; then LD=$CC; fi +echo "$as_me:$LINENO: result: LD defaults to $LD" >&5 +echo "${ECHO_T}LD defaults to $LD" >&6 +fi; export LD + + + +# Check whether --with-ccopts or --without-ccopts was given. +if test "${with_ccopts+set}" = set; then + withval="$with_ccopts" + echo "$as_me:$LINENO: result: CCOPTS is $withval" >&5 +echo "${ECHO_T}CCOPTS is $withval" >&6 +CCOPTS=$withval +CFLAGS="$CFLAGS $withval" +else + CCOPTS= +fi; + + +# Check whether --with-ldopts or --without-ldopts was given. +if test "${with_ldopts+set}" = set; then + withval="$with_ldopts" + echo "$as_me:$LINENO: result: LDFLAGS is $withval" >&5 +echo "${ECHO_T}LDFLAGS is $withval" >&6 +LDOPTS=$withval +LDFLAGS="$LDFLAGS $withval" +else + LDOPTS= +fi; + + +# Check whether --with-binowner or --without-binowner was given. +if test "${with_binowner+set}" = set; then + withval="$with_binowner" + echo "$as_me:$LINENO: result: BINOWNER is $withval" >&5 +echo "${ECHO_T}BINOWNER is $withval" >&6 +BINOWNER=$withval +else + BINOWNER=root +echo "BINOWNER defaults to $BINOWNER" + +fi; + + +# Check whether --with-bingrp or --without-bingrp was given. +if test "${with_bingrp+set}" = set; then + withval="$with_bingrp" + echo "$as_me:$LINENO: result: BINGRP is $withval" >&5 +echo "${ECHO_T}BINGRP is $withval" >&6 +BINGRP=$withval +else + BINGRP=tty +echo "BINGRP defaults to $BINGRP" + +fi; + + +# Check whether --with-binmode or --without-binmode was given. +if test "${with_binmode+set}" = set; then + withval="$with_binmode" + echo "$as_me:$LINENO: result: BINMODE is $withval" >&5 +echo "${ECHO_T}BINMODE is $withval" >&6 +BINMODE=$withval +else + BINMODE=0755 +echo "BINMODE defaults to $BINMODE" + +fi; + + +# Check whether --with-manowner or --without-manowner was given. +if test "${with_manowner+set}" = set; then + withval="$with_manowner" + echo "$as_me:$LINENO: result: MANOWNER is $withval" >&5 +echo "${ECHO_T}MANOWNER is $withval" >&6 +MANOWNER=$withval +else + MANOWNER=man +echo "MANOWNER defaults to $MANOWNER" + +fi; + + +# Check whether --with-mangrp or --without-mangrp was given. +if test "${with_mangrp+set}" = set; then + withval="$with_mangrp" + echo "$as_me:$LINENO: result: MANGRP is $withval" >&5 +echo "${ECHO_T}MANGRP is $withval" >&6 +MANGRP=$withval +else + MANGRP=tty +echo "MANGRP defaults to $MANGRP" + +fi; + + +# Check whether --with-manmode or --without-manmode was given. +if test "${with_manmode+set}" = set; then + withval="$with_manmode" + echo "$as_me:$LINENO: result: MANMODE is $withval" >&5 +echo "${ECHO_T}MANMODE is $withval" >&6 +MANMODE=$withval +else + MANMODE=0644 +echo "MANMODE defaults to $MANMODE" + +fi; + + +# Check whether --with-dumpdatespath or --without-dumpdatespath was given. +if test "${with_dumpdatespath+set}" = set; then + withval="$with_dumpdatespath" + echo "$as_me:$LINENO: result: DUMPDATESPATH is $withval" >&5 +echo "${ECHO_T}DUMPDATESPATH is $withval" >&6 +DUMPDATESPATH=$withval +else + DUMPDATESPATH="${sysconfdir}/dumpdates" +echo "DUMPDATESPATH defaults to $DUMPDATESPATH" + +fi; + +echo "$as_me:$LINENO: checking for ext2fs/ext2fs.h" >&5 +echo $ECHO_N "checking for ext2fs/ext2fs.h... $ECHO_C" >&6 +if test "${ac_cv_header_ext2fs_ext2fs_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_ext2fs_ext2fs_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_ext2fs_ext2fs_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_ext2fs_ext2fs_h" >&5 +echo "${ECHO_T}$ac_cv_header_ext2fs_ext2fs_h" >&6 +if test $ac_cv_header_ext2fs_ext2fs_h = yes; then + ext2fs_h=yes +else + ext2fs_h=no +fi + + +echo "$as_me:$LINENO: checking for ext2fs_open in -lext2fs" >&5 +echo $ECHO_N "checking for ext2fs_open in -lext2fs... $ECHO_C" >&6 +if test "${ac_cv_lib_ext2fs_ext2fs_open+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lext2fs -lcom_err $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char ext2fs_open (); +int +main () +{ +ext2fs_open (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ext2fs_ext2fs_open=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_ext2fs_ext2fs_open=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_ext2fs_ext2fs_open" >&5 +echo "${ECHO_T}$ac_cv_lib_ext2fs_ext2fs_open" >&6 +if test $ac_cv_lib_ext2fs_ext2fs_open = yes; then + ext2fs_lib=yes +else + ext2fs_lib=no +fi + +if test "$ext2fs_h" = no -o "$ext2fs_lib" = no; then + { { echo "$as_me:$LINENO: error: You need to install the Ext2fs libraries from the E2fsprogs distribution first - hint: make install-libs" >&5 +echo "$as_me: error: You need to install the Ext2fs libraries from the E2fsprogs distribution first - hint: make install-libs" >&2;} + { (exit 1); exit 1; }; } +fi + + +for ac_header in ext2fs/ext2_fs.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +echo "$as_me:$LINENO: checking for ext2_ino_t type in libext2fs headers" >&5 +echo $ECHO_N "checking for ext2_ino_t type in libext2fs headers... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +int +main () +{ +ext2_ino_t ino = 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_EXT2_INO_T 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +echo "$as_me:$LINENO: checking for s_journal_inum field in ext2_super_block struct" >&5 +echo $ECHO_N "checking for s_journal_inum field in ext2_super_block struct... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +int +main () +{ +struct ext2_super_block es; es.s_journal_inum = 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_EXT2_JOURNAL_INUM 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +echo "$as_me:$LINENO: checking for blkid/blkid.h" >&5 +echo $ECHO_N "checking for blkid/blkid.h... $ECHO_C" >&6 +if test "${ac_cv_header_blkid_blkid_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_blkid_blkid_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_blkid_blkid_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_blkid_blkid_h" >&5 +echo "${ECHO_T}$ac_cv_header_blkid_blkid_h" >&6 +if test $ac_cv_header_blkid_blkid_h = yes; then + blkid_h=yes +else + blkid_h=no +fi + + +echo "$as_me:$LINENO: checking for blkid_get_devname in -lblkid" >&5 +echo $ECHO_N "checking for blkid_get_devname in -lblkid... $ECHO_C" >&6 +if test "${ac_cv_lib_blkid_blkid_get_devname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lblkid -luuid $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char blkid_get_devname (); +int +main () +{ +blkid_get_devname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_blkid_blkid_get_devname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_blkid_blkid_get_devname=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_blkid_blkid_get_devname" >&5 +echo "${ECHO_T}$ac_cv_lib_blkid_blkid_get_devname" >&6 +if test $ac_cv_lib_blkid_blkid_get_devname = yes; then + blkid_lib=yes +else + blkid_lib=no +fi + +if test "$blkid_h" = yes -a "$blkid_lib" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BLKID 1 +_ACEOF + + BLKID="-lblkid -luuid" +fi + + +echo "$as_me:$LINENO: checking for tgetent in -ltermcap" >&5 +echo $ECHO_N "checking for tgetent in -ltermcap... $ECHO_C" >&6 +if test "${ac_cv_lib_termcap_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ltermcap $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_termcap_tgetent=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_termcap_tgetent=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_termcap_tgetent" >&5 +echo "${ECHO_T}$ac_cv_lib_termcap_tgetent" >&6 +if test $ac_cv_lib_termcap_tgetent = yes; then + termcap_lib=yes +else + termcap_lib=no +fi + +if test "$termcap_lib" = no; then + if test "$READLINE" = "-lreadline -ltermcap"; then + { { echo "$as_me:$LINENO: error: You need to install the GNU termcap library or configure without --enable-readline" >&5 +echo "$as_me: error: You need to install the GNU termcap library or configure without --enable-readline" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +echo "$as_me:$LINENO: checking for readline/readline.h" >&5 +echo $ECHO_N "checking for readline/readline.h... $ECHO_C" >&6 +if test "${ac_cv_header_readline_readline_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_readline_readline_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_readline_readline_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_readline_readline_h" >&5 +echo "${ECHO_T}$ac_cv_header_readline_readline_h" >&6 +if test $ac_cv_header_readline_readline_h = yes; then + readline_h=yes +else + readline_h=no +fi + + +echo "$as_me:$LINENO: checking for readline in -lreadline" >&5 +echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6 +if test "${ac_cv_lib_readline_readline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline "-ltermcap" $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char readline (); +int +main () +{ +readline (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_readline_readline=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_readline_readline=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6 +if test $ac_cv_lib_readline_readline = yes; then + readline_lib=yes +else + readline_lib=no +fi + +if test "$readline_h" = no -o "$readline_lib" = no; then + if test "$READLINE" = "-lreadline -ltermcap"; then + { { echo "$as_me:$LINENO: error: You need to install the GNU readline library or configure without --enable-readline" >&5 +echo "$as_me: error: You need to install the GNU readline library or configure without --enable-readline" >&2;} + { (exit 1); exit 1; }; } + fi +fi + +echo "$as_me:$LINENO: checking for rl_completion_matches in -lreadline" >&5 +echo $ECHO_N "checking for rl_completion_matches in -lreadline... $ECHO_C" >&6 +if test "${ac_cv_lib_readline_rl_completion_matches+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline "-ltermcap" $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char rl_completion_matches (); +int +main () +{ +rl_completion_matches (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_readline_rl_completion_matches=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_readline_rl_completion_matches=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_readline_rl_completion_matches" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_rl_completion_matches" >&6 +if test $ac_cv_lib_readline_rl_completion_matches = yes; then + rlcm=yes +else + rlcm=no +fi + +if test "$rlcm" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_READLINE_RLCM 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for rl_completion_append_character in -lreadline" >&5 +echo $ECHO_N "checking for rl_completion_append_character in -lreadline... $ECHO_C" >&6 +if test "${ac_cv_lib_readline_rl_completion_append_character+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline "-ltermcap" $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char rl_completion_append_character (); +int +main () +{ +rl_completion_append_character (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_readline_rl_completion_append_character=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_readline_rl_completion_append_character=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_readline_rl_completion_append_character" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_rl_completion_append_character" >&6 +if test $ac_cv_lib_readline_rl_completion_append_character = yes; then + rcac=yes +else + rcac=no +fi + +if test "$rcac" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_READLINE_CAC 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for zlib.h" >&5 +echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_zlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_zlib_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_zlib_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_zlib_h" >&6 +if test $ac_cv_header_zlib_h = yes; then + zlib_h=yes +else + zlib_h=no +fi + + +echo "$as_me:$LINENO: checking for compress2 in -lz" >&5 +echo $ECHO_N "checking for compress2 in -lz... $ECHO_C" >&6 +if test "${ac_cv_lib_z_compress2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char compress2 (); +int +main () +{ +compress2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_compress2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_z_compress2=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5 +echo "${ECHO_T}$ac_cv_lib_z_compress2" >&6 +if test $ac_cv_lib_z_compress2 = yes; then + zlib_lib=yes +else + zlib_lib=no +fi + +if test "$zlib_h" = yes -a "$zlib_lib" = yes; then + if test "$STATICZ" = yes; then + ZLIB="-Wl,-Bstatic -lz -Wl,-Bdynamic" + else + ZLIB="-lz" + fi + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ZLIB 1 +_ACEOF + +else + ZLIB="" +fi + + +echo "$as_me:$LINENO: checking for bzlib.h" >&5 +echo $ECHO_N "checking for bzlib.h... $ECHO_C" >&6 +if test "${ac_cv_header_bzlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_bzlib_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_bzlib_h=no +fi +rm -f conftest.err conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_header_bzlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_bzlib_h" >&6 +if test $ac_cv_header_bzlib_h = yes; then + bzlib_h=yes +else + bzlib_h=no +fi + + +echo "$as_me:$LINENO: checking for BZ2_bzBuffToBuffCompress in -lbz2" >&5 +echo $ECHO_N "checking for BZ2_bzBuffToBuffCompress in -lbz2... $ECHO_C" >&6 +if test "${ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char BZ2_bzBuffToBuffCompress (); +int +main () +{ +BZ2_bzBuffToBuffCompress (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress" >&5 +echo "${ECHO_T}$ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress" >&6 +if test $ac_cv_lib_bz2_BZ2_bzBuffToBuffCompress = yes; then + bzlib_lib=yes +else + bzlib_lib=no +fi + +if test "$bzlib_h" = yes -a "$bzlib_lib" = yes; then + if test "$STATICZ" = yes; then + BZLIB="-Wl,-Bstatic -lbz2 -Wl,-Bdynamic" + else + BZLIB="-lbz2" + fi + +cat >>confdefs.h <<\_ACEOF +#define HAVE_BZLIB 1 +_ACEOF + +else + BZLIB="" +fi + + + + + + + + + + + + +for ac_func in err errx verr verrx vwarn vwarnx warn warnx realpath lchown +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +echo "$as_me:$LINENO: checking for glob" >&5 +echo $ECHO_N "checking for glob... $ECHO_C" >&6 +if test "${ac_cv_func_glob+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define glob to an innocuous variant, in case declares glob. + For example, HP-UX 11i declares gettimeofday. */ +#define glob innocuous_glob + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char glob (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef glob + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char glob (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_glob) || defined (__stub___glob) +choke me +#else +char (*f) () = glob; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != glob; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_glob=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_glob=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_glob" >&5 +echo "${ECHO_T}$ac_cv_func_glob" >&6 + + +echo "$as_me:$LINENO: checking for extended glob routines" >&5 +echo $ECHO_N "checking for extended glob routines... $ECHO_C" >&6 +if test "$ac_cv_func_glob" = "yes"; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +# include +# ifdef GLOB_ALTDIRFUNC + yes +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GLOB 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +else + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + echo "Your system does not support extended glob, will use the internal routines" + +fi +rm -f conftest* + +fi + +if test "$ERMT" != ""; then + if test "${ac_cv_header_openssl_evp_h+set}" = set; then + echo "$as_me:$LINENO: checking for openssl/evp.h" >&5 +echo $ECHO_N "checking for openssl/evp.h... $ECHO_C" >&6 +if test "${ac_cv_header_openssl_evp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_openssl_evp_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_evp_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking openssl/evp.h usability" >&5 +echo $ECHO_N "checking openssl/evp.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking openssl/evp.h presence" >&5 +echo $ECHO_N "checking openssl/evp.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: openssl/evp.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: openssl/evp.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: openssl/evp.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: openssl/evp.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: openssl/evp.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: openssl/evp.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: openssl/evp.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/evp.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: openssl/evp.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for openssl/evp.h" >&5 +echo $ECHO_N "checking for openssl/evp.h... $ECHO_C" >&6 +if test "${ac_cv_header_openssl_evp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_openssl_evp_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_openssl_evp_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_evp_h" >&6 + +fi +if test $ac_cv_header_openssl_evp_h = yes; then + evp_h=yes +else + evp_h=no +fi + + + echo "$as_me:$LINENO: checking for EVP_CIPHER_CTX_set_padding in -lcrypto" >&5 +echo $ECHO_N "checking for EVP_CIPHER_CTX_set_padding in -lcrypto... $ECHO_C" >&6 +if test "${ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char EVP_CIPHER_CTX_set_padding (); +int +main () +{ +EVP_CIPHER_CTX_set_padding (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding" >&5 +echo "${ECHO_T}$ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding" >&6 +if test $ac_cv_lib_crypto_EVP_CIPHER_CTX_set_padding = yes; then + crypto_lib=yes +else + crypto_lib=no +fi + + if test "$evp_h" = no -o "$crypto_lib" = no; then + { { echo "$as_me:$LINENO: error: You need to install the OpenSSL library (version 0.9.7a or later)" >&5 +echo "$as_me: error: You need to install the OpenSSL library (version 0.9.7a or later)" >&2;} + { (exit or configure without --enable-ermt); exit or configure without --enable-ermt; }; } + fi +fi + +echo "$as_me:$LINENO: checking for quad_t" >&5 +echo $ECHO_N "checking for quad_t... $ECHO_C" >&6 +if test "${ac_cv_type_quad_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((quad_t *) 0) + return 0; +if (sizeof (quad_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_quad_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_quad_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_quad_t" >&5 +echo "${ECHO_T}$ac_cv_type_quad_t" >&6 +if test $ac_cv_type_quad_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define quad_t int64_t +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for u_quad_t" >&5 +echo $ECHO_N "checking for u_quad_t... $ECHO_C" >&6 +if test "${ac_cv_type_u_quad_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((u_quad_t *) 0) + return 0; +if (sizeof (u_quad_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_u_quad_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_u_quad_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_u_quad_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_quad_t" >&6 +if test $ac_cv_type_u_quad_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define u_quad_t uint64_t +_ACEOF + +fi + + +top_builddir=`cd .; pwd` + + +test -d compat || mkdir compat +test -d compat/lib || mkdir compat/lib + + ac_config_files="$ac_config_files MCONFIG Makefile common/Makefile compat/include/Makefile compat/lib/Makefile dump/Makefile restore/Makefile $RMTMAKEFILE" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "MCONFIG" ) CONFIG_FILES="$CONFIG_FILES MCONFIG" ;; + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "common/Makefile" ) CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; + "compat/include/Makefile" ) CONFIG_FILES="$CONFIG_FILES compat/include/Makefile" ;; + "compat/lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES compat/lib/Makefile" ;; + "dump/Makefile" ) CONFIG_FILES="$CONFIG_FILES dump/Makefile" ;; + "restore/Makefile" ) CONFIG_FILES="$CONFIG_FILES restore/Makefile" ;; + "$RMTMAKEFILE" ) CONFIG_FILES="$CONFIG_FILES $RMTMAKEFILE" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@LN_S@,$LN_S,;t t +s,@CP@,$CP,;t t +s,@MV@,$MV,;t t +s,@RM@,$RM,;t t +s,@AR@,$AR,;t t +s,@ac_ct_AR@,$ac_ct_AR,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@PATCH@,$PATCH,;t t +s,@ac_ct_PATCH@,$ac_ct_PATCH,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@DUMPDEBUG@,$DUMPDEBUG,;t t +s,@RESTOREDEBUG@,$RESTOREDEBUG,;t t +s,@STATIC@,$STATIC,;t t +s,@RMTDIR@,$RMTDIR,;t t +s,@ERMT@,$ERMT,;t t +s,@CRYPTO@,$CRYPTO,;t t +s,@OPTDEFS@,$OPTDEFS,;t t +s,@READLINE@,$READLINE,;t t +s,@LD@,$LD,;t t +s,@CCOPTS@,$CCOPTS,;t t +s,@LDOPTS@,$LDOPTS,;t t +s,@BINOWNER@,$BINOWNER,;t t +s,@BINGRP@,$BINGRP,;t t +s,@BINMODE@,$BINMODE,;t t +s,@MANOWNER@,$MANOWNER,;t t +s,@MANGRP@,$MANGRP,;t t +s,@MANMODE@,$MANMODE,;t t +s,@DUMPDATESPATH@,$DUMPDATESPATH,;t t +s,@BLKID@,$BLKID,;t t +s,@ZLIB@,$ZLIB,;t t +s,@BZLIB@,$BZLIB,;t t +s,@top_builddir@,$top_builddir,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +/@MCONFIG@/r $MCONFIG +s,@MCONFIG@,,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..bcafc46 --- /dev/null +++ b/configure.in @@ -0,0 +1,576 @@ +AC_INIT(dump/dump.h) +AC_PREREQ(2.57) + +MCONFIG=./MCONFIG +AC_SUBST_FILE(MCONFIG) + +AC_CONFIG_HEADER(config.h) + +dnl +dnl Check for programs +dnl +AC_PROG_MAKE_SET +AC_PROG_LN_S +AC_PATH_PROG(CP, cp, cp) +AC_PATH_PROG(MV, mv, mv) +AC_PATH_PROG(RM, rm, rm) +AC_CHECK_TOOL(AR, ar, ar) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(PATCH, patch, :) +AC_PROG_CC +AC_PROG_INSTALL + +AC_CHECK_HEADERS([sys/types.h]) + +CPPFLAGS="-D_BSD_SOURCE -D_USE_BSD_SIGNAL ${CPPFLAGS}" + +dnl +dnl Handle --enable-debug +dnl +AC_ARG_ENABLE([debug], +[ --enable-debug include debugging code (default is NO)], +if test "$enableval" = "no" +then + DUMPDEBUG="" + RESTOREDEBUG="" + echo "Not including debugging code" +else + DUMPDEBUG="-DFDEBUG -DTDEBUG -DWRITEDEBUG -DDIRDEBUG" + RESTOREDEBUG="-DDIRDEBUG" + echo "Including debugging code" +fi, +DUMPDEBUG="" +RESTOREDEBUG="" +echo "Not including debugging code by default" +) +AC_SUBST(DUMPDEBUG) +AC_SUBST(RESTOREDEBUG) + +dnl +dnl Handle --enable-static +dnl +AC_ARG_ENABLE([static], +[ --enable-static link dump and restore statically (default is NO)], +if test "$enableval" = "no" +then + STATIC="" + echo "Linking dump and restore dynamically" +else + STATIC="-static" + echo "Linking dump and restore statically" +fi +, +STATIC="" +echo "Linking dump and restore dynamically by default" +) +AC_SUBST(STATIC) + +dnl +dnl Handle --enable-staticz +dnl +AC_ARG_ENABLE([staticz], +[ --enable-staticz link libz and libbz2 statically (default is NO)], +if test "$enableval" = "no" +then + STATICZ="no" + echo "Linking libz and libbz2 dynamically" +else + STATICZ="yes" + echo "Linking libz and libbz2 statically" +fi +, +STATICZ="no" +echo "Linking libz and libbz2 dynamically by default" +) + +dnl +dnl Handle --enable-rmt +dnl +AC_ARG_ENABLE([rmt], +[ --enable-rmt compile and install rmt (default is YES)], +if test "$enableval" = "no" +then + RMTDIR="" + RMTMAKEFILE="" + echo "Not compiling rmt" +else + RMTDIR="rmt" + RMTMAKEFILE="rmt/Makefile" + echo "Compiling rmt" +fi +, +RMTDIR="rmt" +RMTMAKEFILE="rmt/Makefile" +echo "Compiling rmt by default" +) +AC_SUBST(RMTDIR) + +dnl +dnl Handle --enable-ermt +dnl +AC_ARG_ENABLE([ermt], +[ --enable-ermt compile ermt, an encrypting version of rmt (default is NO)], +if test "$enableval" = "no" +then + ERMT="" + CRYPTO="" + echo "Not compiling ermt" +else + if test "$RMTDIR" = "" + then + AC_MSG_ERROR(ermt requires --enable-rmt) + fi + ERMT="ermt" + CRYPTO="-lcrypto" + echo "Compiling ermt" +fi +, +ERMT="" +CRYPTO="" +echo "Not compiling ermt by default" +) +AC_SUBST(ERMT) +AC_SUBST(CRYPTO) + +dnl +dnl Handle --enable-kerberos +dnl +AC_ARG_ENABLE([kerberos], +[ --enable-kerberos compile kerberos extensions (default is NO)], +if test "$enableval" = "yes" +then + OPTDEFS="-DKERBEROS" + echo "Compiling kerberos extensions" +else + OPTDEFS="" + echo "Not compiling kerberos extensions" +fi +, +OPTDEFS="" +echo "Not compiling kerberos extensions by default" +) +AC_SUBST(OPTDEFS) + +dnl +dnl Handle --enable-readline +dnl +AC_ARG_ENABLE([readline], +[ --enable-readline enable readline support in restore (default is YES)], +if test "$enableval" = "no" +then + READLINE="" + echo "Not including readline support" +else + READLINE="-lreadline -ltermcap" + AC_DEFINE([HAVE_READLINE],1,[Define if you want to include readline support.]) + echo "Including readline support" +fi +, +READLINE="-lreadline -ltermcap" +AC_DEFINE([HAVE_READLINE],1,[Define if you want to include readline support.]) +echo "Including readline support by default" +) +AC_SUBST(READLINE) + +dnl +dnl Handle --enable-oldsylefscript +dnl +AC_ARG_ENABLE([oldstylefscript], +[ --enable-oldstylefscript enable old style F script (no arguments) (default is NO)], +if test "$enableval" = "yes" +then + AC_DEFINE([OLD_STYLE_FSCRIPT],1,[Define this is you want old style F script (no arguments).]) + echo "Using old style F script" +else + echo "Using new style F script" +fi +, +echo "Using new style F script by default" +) + +dnl +dnl Handle --enable-largefile +dnl +AC_ARG_ENABLE([largefile], +[ --enable-largefile enable Large File System support (default is YES)], +if test "$enableval" = "yes" +then + AC_DEFINE([USE_LFS],1,[Define this if you want Large File System support.]) + echo "Enabling Large File System support" +else + echo "Not enabling Large File System support" +fi +, +AC_DEFINE([USE_LFS],1,[Define this if you want Large File System support.]) +echo "Enabling Large File System support by default" +) + +dnl +dnl Handle --enable-qfa +dnl +AC_ARG_ENABLE([qfa], +[ --enable-qfa enable Quick File Access support (default is YES)], +if test "$enableval" = "yes" +then + AC_DEFINE([USE_QFA],1,[Define this if you want Quick File Access support.]) + echo "Enabling Quick File Access support" +else + echo "Not enabling Quick File Access support" +fi +, +AC_DEFINE([USE_QFA],1,[Define this if you want Quick File Access support.]) +echo "Enabling Quick File Access support by default" +) + +dnl +dnl Handle --enable-qfadebug +dnl +AC_ARG_ENABLE([qfadebug], +[ --enable-qfadebug include Quick File Access debugging code (default is NO)], +if test "$enableval" = "yes" +then + AC_DEFINE([DEBUG_QFA],1,[Define this if you want to include Quick File Access debugging code.]) + echo "Including Quick File Access debugging code" +else + echo "Not including Quick File Access debugging code" +fi +, +echo "Not including Quick File Access debugging code by default" +) + +dnl +dnl Handle --enable-macosx +dnl +AC_ARG_ENABLE([macosx], +[ --enable-macosx include Mac OSX restore compatibility (default is NO)], +if test "$enableval" = "yes" +then + AC_DEFINE([DUMP_MACOSX],1,[Define this if you want to include Mac OSX restore compatibility.]) + echo "Including Mac OSX restore compatibility code" +else + echo "Not including Mac OSX restore compatibility code" +fi +, +echo "Not including Mac OSX restore compatibility code by default" +) + + +dnl +dnl set $(CC) from --with-cc=value +dnl +AC_ARG_WITH([cc], +[ --with-cc=COMPILER select compiler to use], +AC_MSG_RESULT(CC=$withval) +CC=$withval, +if test -z "$CC" ; then CC=cc; fi +[AC_MSG_RESULT(CC defaults to $CC)])dnl +export CC +AC_SUBST([CC]) + +dnl +dnl set $(LD) from --with-linker=value +dnl +AC_ARG_WITH([linker], +[ --with-linker=LINKER select linker to use], +AC_MSG_RESULT(LD=$withval) +LD=$withval, +if test -z "$LD" ; then LD=$CC; fi +[AC_MSG_RESULT(LD defaults to $LD)])dnl +export LD +AC_SUBST([LD]) + +dnl +dnl set $(CCOPTS) from --with-ccopts=value +dnl +AC_ARG_WITH([ccopts], +[ --with-ccopts=CCOPTS select compiler command line options], +AC_MSG_RESULT(CCOPTS is $withval) +CCOPTS=$withval +CFLAGS="$CFLAGS $withval", +CCOPTS=)dnl +AC_SUBST(CCOPTS) + +dnl +dnl set $(LDFLAGS) from --with-ldopts=value +dnl +AC_ARG_WITH([ldopts], +[ --with-ldopts=LDOPTS select linker command line options], +AC_MSG_RESULT(LDFLAGS is $withval) +LDOPTS=$withval +LDFLAGS="$LDFLAGS $withval", +LDOPTS=)dnl +AC_SUBST(LDOPTS) + +dnl +dnl set $(BINOWNER) from --with-binowner +dnl +AC_ARG_WITH([binowner], +[ --with-binowner=USER select owner for binaries], +AC_MSG_RESULT(BINOWNER is $withval) +BINOWNER=$withval, +BINOWNER=root +echo "BINOWNER defaults to $BINOWNER" +)dnl +AC_SUBST(BINOWNER) + +dnl +dnl set $(BINGRP) from --with-bingrp +dnl +AC_ARG_WITH([bingrp], +[ --with-bingrp=GROUP select group for binaries], +AC_MSG_RESULT(BINGRP is $withval) +BINGRP=$withval, +BINGRP=tty +echo "BINGRP defaults to $BINGRP" +)dnl +AC_SUBST(BINGRP) + +dnl +dnl set $(BINMODE) from --with-binmode +dnl +AC_ARG_WITH([binmode], +[ --with-binmode=MODE select mode for binaries], +AC_MSG_RESULT(BINMODE is $withval) +BINMODE=$withval, +BINMODE=0755 +echo "BINMODE defaults to $BINMODE" +)dnl +AC_SUBST(BINMODE) + +dnl +dnl set $(MANOWNER) from --with-manowner +dnl +AC_ARG_WITH([manowner], +[ --with-manowner=USER select owner for manual pages], +AC_MSG_RESULT(MANOWNER is $withval) +MANOWNER=$withval, +MANOWNER=man +echo "MANOWNER defaults to $MANOWNER" +)dnl +AC_SUBST(MANOWNER) + +dnl +dnl set $(MANGRP) from --with-mangrp +dnl +AC_ARG_WITH([mangrp], +[ --with-mangrp=GROUP select group for manual pages], +AC_MSG_RESULT(MANGRP is $withval) +MANGRP=$withval, +MANGRP=tty +echo "MANGRP defaults to $MANGRP" +)dnl +AC_SUBST(MANGRP) + +dnl +dnl set $(MANMODE) from --with-manmode +dnl +AC_ARG_WITH([manmode], +[ --with-manmode=MODE select mode for manual pages], +AC_MSG_RESULT(MANMODE is $withval) +MANMODE=$withval, +MANMODE=0644 +echo "MANMODE defaults to $MANMODE" +)dnl +AC_SUBST(MANMODE) + +dnl +dnl set $(DUMPDATESPATH) from --with-dumpdatespath +dnl +AC_ARG_WITH([dumpdatespath], +[ --with-dumpdatespath=PATH select path for dumpdates file], +AC_MSG_RESULT(DUMPDATESPATH is $withval) +DUMPDATESPATH=$withval, +DUMPDATESPATH="${sysconfdir}/dumpdates" +echo "DUMPDATESPATH defaults to $DUMPDATESPATH" +)dnl +AC_SUBST(DUMPDATESPATH) + +dnl +dnl Check for Ext2fs headers and libraries +dnl +AC_CHECK_HEADER(ext2fs/ext2fs.h, [ext2fs_h=yes], [ext2fs_h=no], [-]) +AC_CHECK_LIB(ext2fs, ext2fs_open, [ext2fs_lib=yes], [ext2fs_lib=no], [-lcom_err]) +if test "$ext2fs_h" = no -o "$ext2fs_lib" = no; then + AC_MSG_ERROR(You need to install the Ext2fs libraries from the E2fsprogs distribution first - hint: make install-libs) +fi + +dnl +dnl Try to use ext2_fs.h header from libext2fs instead of from the kernel +dnl +AC_CHECK_HEADERS(ext2fs/ext2_fs.h, [], [], [-]) + +dnl +dnl Check for ext2_ino_t type +dnl +AC_MSG_CHECKING(for ext2_ino_t type in libext2fs headers) +AC_TRY_COMPILE([#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include ], +[ext2_ino_t ino = 0;], +[AC_DEFINE([HAVE_EXT2_INO_T],1,[Define if we have the ext2_ino_t type (from e2fsprogs 1.20+).]) + AC_MSG_RESULT(yes)], +AC_MSG_RESULT(no)) + +dnl +dnl Check for s_journal_inum field in ext2_super_block struct +dnl +AC_MSG_CHECKING(for s_journal_inum field in ext2_super_block struct) +AC_TRY_COMPILE([#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include ], +[struct ext2_super_block es; es.s_journal_inum = 0;], +[AC_DEFINE([HAVE_EXT2_JOURNAL_INUM],1,[Define if we have the s_journal_inum field in struct ext2_super_block.]) + AC_MSG_RESULT(yes)], +AC_MSG_RESULT(no)) + +dnl +dnl Check for blkid headers libraries +dnl +AC_CHECK_HEADER(blkid/blkid.h, [blkid_h=yes], [blkid_h=no], [-]) +AC_CHECK_LIB(blkid, blkid_get_devname, [blkid_lib=yes], [blkid_lib=no], [-luuid]) +if test "$blkid_h" = yes -a "$blkid_lib" = yes; then + AC_DEFINE([HAVE_BLKID],1,[Define this if you have the blkid library.]) + BLKID="-lblkid -luuid" +fi +AC_SUBST(BLKID) + +dnl +dnl Check for termcap libraries +dnl +AC_CHECK_LIB(termcap, tgetent, [termcap_lib=yes], [termcap_lib=no]) +if test "$termcap_lib" = no; then + if test "$READLINE" = "-lreadline -ltermcap"; then + AC_MSG_ERROR(You need to install the GNU termcap library or configure without --enable-readline) + fi +fi + +dnl +dnl Check for readline headers and libraries +dnl +AC_CHECK_HEADER(readline/readline.h, [readline_h=yes], [readline_h=no], [-]) +AC_CHECK_LIB(readline, readline, [readline_lib=yes], [readline_lib=no], "-ltermcap") +if test "$readline_h" = no -o "$readline_lib" = no; then + if test "$READLINE" = "-lreadline -ltermcap"; then + AC_MSG_ERROR(You need to install the GNU readline library or configure without --enable-readline) + fi +fi + +dnl +dnl Check for rl_completion_matches +dnl +AC_CHECK_LIB(readline, rl_completion_matches, [rlcm=yes], [rlcm=no], "-ltermcap") +if test "$rlcm" = yes; then + AC_DEFINE([HAVE_READLINE_RLCM],1,[Define this if your readline libs have the rl_completion_matches library.]) +fi + +dnl +dnl Check for rl_completion_append_character +dnl +AC_CHECK_LIB(readline, rl_completion_append_character, [rcac=yes], [rcac=no], "-ltermcap") +if test "$rcac" = yes; then + AC_DEFINE([HAVE_READLINE_CAC],1,[Define this if your readline libs have the rl_completion_append_character variable.]) +fi + +dnl +dnl Check for zlib headers and libraries +dnl +AC_CHECK_HEADER(zlib.h, [zlib_h=yes], [zlib_h=no], [-]) +AC_CHECK_LIB(z, compress2, [zlib_lib=yes], [zlib_lib=no]) +if test "$zlib_h" = yes -a "$zlib_lib" = yes; then + if test "$STATICZ" = yes; then + ZLIB="-Wl,-Bstatic -lz -Wl,-Bdynamic" + else + ZLIB="-lz" + fi + AC_DEFINE([HAVE_ZLIB],1,[Define this if you have zlib compression library.]) +else + ZLIB="" +fi +AC_SUBST(ZLIB) + +dnl +dnl Check for bzlib headers and libraries +dnl +AC_CHECK_HEADER(bzlib.h, [bzlib_h=yes], [bzlib_h=no], [-]) +AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress, [bzlib_lib=yes], [bzlib_lib=no]) +if test "$bzlib_h" = yes -a "$bzlib_lib" = yes; then + if test "$STATICZ" = yes; then + BZLIB="-Wl,-Bstatic -lbz2 -Wl,-Bdynamic" + else + BZLIB="-lbz2" + fi + AC_DEFINE([HAVE_BZLIB],1,[Define this if you have bzlib compression library.]) +else + BZLIB="" +fi +AC_SUBST(BZLIB) + +dnl +dnl Check for library functions +dnl +AC_CHECK_FUNCS(err errx verr verrx vwarn vwarnx warn warnx realpath lchown) +AC_CHECK_FUNC(glob) + +dnl +dnl Check for GLOB_ALTDIRFUNC +dnl +AC_MSG_CHECKING(for extended glob routines) +if test "$ac_cv_func_glob" = "yes"; then + AC_EGREP_CPP(yes, + [ +# include +# ifdef GLOB_ALTDIRFUNC + yes +# endif + ], + [ + AC_DEFINE([HAVE_GLOB],1,[Define if you have the glob function.]) + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + echo "Your system does not support extended glob, will use the internal routines" + ]) +fi + +dnl +dnl Check for OpenSSL, for ermt +dnl +if test "$ERMT" != ""; then + AC_CHECK_HEADER(openssl/evp.h, [evp_h=yes], [evp_h=no]) + AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_set_padding, [crypto_lib=yes], [crypto_lib=no]) + if test "$evp_h" = no -o "$crypto_lib" = no; then + AC_MSG_ERROR(You need to install the OpenSSL library (version 0.9.7a or later), or configure without --enable-ermt) + fi +fi + +dnl +dnl Check for types +dnl +AC_CHECK_TYPE(quad_t, int64_t) +AC_CHECK_TYPE(u_quad_t, uint64_t) + +dnl +dnl Compute top_buildir +dnl +top_builddir=`cd .; pwd` +AC_SUBST(top_builddir) + +dnl +dnl Create directories +dnl +test -d compat || mkdir compat +test -d compat/lib || mkdir compat/lib + +dnl +dnl Output files +dnl +AC_OUTPUT(MCONFIG Makefile common/Makefile compat/include/Makefile compat/lib/Makefile dump/Makefile restore/Makefile $RMTMAKEFILE) diff --git a/depfix.sed b/depfix.sed new file mode 100644 index 0000000..4ed209a --- /dev/null +++ b/depfix.sed @@ -0,0 +1,34 @@ +# $Id: depfix.sed,v 1.2 1999/10/11 13:31:04 stelian Exp $ +# +# Insert the header..... +# +1i\ +# +++ Dependency line eater +++\ +# \ +# Makefile dependencies follow. This must be the last section in\ +# the Makefile.in file\ +# + +# +# Remove line continuations.... +# +#:FIRST +#y/ / / +#s/^ *// +#/\\$/{ +#N +#y/ / / +#s/\\\n */ / +#bFIRST +#} +#s/ */ /g + +s;/usr/include/[^ ]* *;;g +s;/usr/lib/[^ ]* *;;g +s;/mit/cygnus[^ ]* *;;g + +# +# Now insert a trailing newline... +# +$a\ + diff --git a/dump.lsm b/dump.lsm new file mode 100644 index 0000000..73f53f7 --- /dev/null +++ b/dump.lsm @@ -0,0 +1,18 @@ +Begin3 +Title: dump and restore for Ext2fs +Version: 0.4b37 +Entered-date: 07JUL04 +Description: Port of the 4.4BSD dump and restore backup suite +Keywords: backup, filesystem, Ext2fs +Author: University of California, Berkeley +Maintained-by: stelian@popies.net (Stelian Pop) +Primary-site: http://dump.sourceforge.net/ + 0kB dump-0.4b37.tar.gz + 0 dump.lsm +Original-site: ftp.freebsd.org /pub/bsd-sources/4.4BSD-Lite2/sbin + dump/* + restore/* +Platforms: linux 2.0.x, linux 2.2.x, linux 2.4.x, linux 2.6.x + e2fsprogs 1.14 or better +Copying-policy: BSD +End diff --git a/dump.spec b/dump.spec new file mode 100644 index 0000000..ae0c08e --- /dev/null +++ b/dump.spec @@ -0,0 +1,300 @@ +%define _sbindir /sbin +# XXX --enable-kerberos needs krcmd +%define myoptions --with-binmode=6755 --with-manowner=root --with-mangrp=root --with-manmode=0644 --with-dumpdates="%{_sysconfdir}/dumpdates" + +Summary: Programs for backing up and restoring ext2/ext3 filesystems. +Name: dump +Version: 0.4b37 +Release: 1 +License: BSD +URL: http://dump.sourceforge.net +Group: Applications/Archiving +Source: dump-%{version}.tar.gz +BuildPrereq: e2fsprogs-devel >= 1.18 +BuildPrereq: libtermcap-devel, readline-devel +BuildPrereq: zlib-devel, bzip2-devel +Requires: rmt +BuildRoot: %{_tmppath}/%{name}-root + +%description +The dump package contains both dump and restore. Dump examines files +in a filesystem, determines which ones need to be backed up, and +copies those files to a specified disk, tape, or other storage medium. +The restore command performs the inverse function of dump; it can +restore a full backup of a filesystem. Subsequent incremental backups +can then be layered on top of the full backup. Single files and +directory subtrees may also be restored from full or partial backups. + +Install dump if you need a system for both backing up filesystems and +restoring filesystems after backups. + +%package -n rmt +Summary: Provides certain programs with access to remote tape devices. +Group: Applications/Archiving + +%description -n rmt +The rmt utility provides remote access to tape devices for programs +like dump (a filesystem backup program), restore (a program for +restoring files from a backup), and tar (an archiving program). + +%package -n dump-static +Summary: Statically linked versions of dump and restore. +Group: Applications/Archiving + +%description -n dump-static +The dump package contains both dump and restore. Dump examines files in +a filesystem, determines which ones need to be backed up, and copies +those files to a specified disk, tape, or other storage medium. The +restore command performs the inverse function of dump; it can restore a +full backup of a filesystem. Subsequent incremental backups can then be +layered on top of the full backup. Single files and directory subtrees +may also be restored from full or partial backups. + +Install dump if you need a system for both backing up filesystems and +restoring filesystems after backups. + +This package contains statically linked versions of dump and restore. + +%prep +%setup -q + +%build +%configure %{myoptions} --enable-static -disable-rmt + +%ifarch alpha +RPM_OPT_FLAGS="" +%endif +make OPT="$RPM_OPT_FLAGS -Wall -Wpointer-arith -Wstrict-prototypes \ + -Wmissing-prototypes -Wno-char-subscripts" + +mv dump/dump dump/dump.static +mv restore/restore restore/restore.static + +make distclean + +%configure %{myoptions} + +make OPT="$RPM_OPT_FLAGS -Wall -Wpointer-arith -Wstrict-prototypes \ + -Wmissing-prototypes -Wno-char-subscripts" + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_sbindir} +mkdir -p %{buildroot}%{_mandir}/man8 + +%makeinstall SBINDIR=%{buildroot}%{_sbindir} MANDIR=%{buildroot}%{_mandir}/man8 BINOWNER=$(id -un) BINGRP=$(id -gn) MANOWNER=$(id -un) MANGRP=$(id -gn) +mkdir -p $RPM_BUILD_ROOT/usr/sbin + +cp dump/dump.static %{buildroot}%{_sbindir} +cp restore/restore.static %{buildroot}%{_sbindir} + +pushd $RPM_BUILD_ROOT + ln -sf dump .%{_sbindir}/rdump + ln -sf dump.static .%{_sbindir}/rdump.static + ln -sf restore .%{_sbindir}/rrestore + ln -sf restore.static .%{_sbindir}/rrestore.static + chmod ug-s .%{_sbindir}/rmt + mkdir -p .%{_sysconfdir} + > .%{_sysconfdir}/dumpdates + ln -sf ..%{_sbindir}/rmt .%{_sysconfdir}/rmt + # quick workaround :) + mv sbin/* usr/sbin/ + mv usr/sbin/*static sbin/ + mv usr/sbin/rmt sbin/ + # somehow, rpm didn't strip these... + strip usr/sbin/* sbin/* || : +popd + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +%doc CHANGES COPYRIGHT KNOWNBUGS MAINTAINERS README REPORTING-BUGS THANKS TODO +%doc dump.lsm examples +%attr(0664,root,disk) %config(noreplace) %{_sysconfdir}/dumpdates +%attr(0755,root,root) /usr/sbin/dump +/usr/sbin/rdump +%attr(0755,root,root) /usr/sbin/restore +/usr/sbin/rrestore +%{_mandir}/man8/dump.* +%{_mandir}/man8/rdump.* +%{_mandir}/man8/restore.* +%{_mandir}/man8/rrestore.* + +%files -n rmt +%defattr(-,root,root) +%attr(0755,root,root) %{_sbindir}/rmt +%{_sysconfdir}/rmt +%{_mandir}/man8/rmt.* + +%files -n dump-static +%defattr(-,root,root) +%attr(0755,root,root) %{_sbindir}/dump.static +%{_sbindir}/rdump.static +%attr(0755,root,root) %{_sbindir}/restore.static +%{_sbindir}/rrestore.static + +%changelog +* Wed Jul 7 2004 Stelian Pop +- dump 0.4b37 released, first packaging. + +* Wed Apr 21 2004 Stelian Pop +- dump 0.4b36 released, first packaging. + +* Sun Dec 21 2003 Stelian Pop +- dump 0.4b35 released, first packaging. + +* Fri Apr 18 2003 Stelian Pop +- dump 0.4b34 released, first packaging. + +* Mon Feb 10 2003 Stelian Pop +- dump 0.4b33 released, first packaging. + +* Fri Nov 15 2002 Stelian Pop +- dump 0.4b32 released, first packaging. + +* Tue Jul 30 2002 Stelian Pop +- dump 0.4b31 released, first packaging. + +* Thu Jul 25 2002 Stelian Pop +- dump 0.4b30 released, first packaging. + +* Sat Jun 8 2002 Stelian Pop +- dump 0.4b29 released, first packaging. + +* Fri Apr 12 2002 Stelian Pop +- dump 0.4b28 released, first packaging. + +* Fri Feb 15 2002 Stelian Pop +- dump 0.4b27 released, first packaging. + +* Mon Jan 7 2002 Stelian Pop +- dump 0.4b26 released, first packaging. + +* Sat Nov 17 2001 Stelian Pop +- dump 0.4b25 released, first packaging. + +* Wed Sep 12 2001 Stelian Pop +- dump 0.4b24 released, first packaging. + +* Fri Jul 20 2001 Stelian Pop +- dump 0.4b23 released, first packaging. + +* Sat May 12 2001 Stelian Pop +- dump 0.4b22 released, first packaging. + +* Sat Jan 30 2001 Stelian Pop +- dump 0.4b21 released, first packaging. + +* Fri Nov 10 2000 Stelian Pop +- dump 0.4b20 released, first packaging. + +* Sun Aug 20 2000 Stelian Pop +- dump 0.4b19 released, first packaging. + +* Thu Jun 30 2000 Stelian Pop +- dump 0.4b18 released, first packaging. + +* Thu Jun 1 2000 Stelian Pop +- dump 0.4b17 released, first packaging. + +* Sat Mar 11 2000 Stelian Pop +- dump 0.4b16 released, first packaging. + +* Thu Mar 2 2000 Stelian Pop +- dump 0.4b15 released, first packaging. + +* Thu Feb 10 2000 Stelian Pop +- dump 0.4b14 released, first packaging. + +* Fri Jan 21 2000 Stelian Pop +- dump 0.4b13 released, first packaging. + +* Fri Jan 8 2000 Stelian Pop +- dump 0.4b12 released, first packaging. + +* Sun Dec 5 1999 Stelian Pop +- dump 0.4b11 released, first packaging. + +* Sun Nov 21 1999 Stelian Pop +- dump 0.4b10 released, first packaging. + +* Thu Nov 11 1999 Stelian Pop +- make static versions also for rescue purposes. + +* Wed Nov 5 1999 Stelian Pop +- dump 0.4b9 released, first packaging. + +* Wed Nov 3 1999 Stelian Pop +- dump 0.4b8 released, first packaging. + +* Thu Oct 8 1999 Stelian Pop +- dump 0.4b7 released, first packaging. + +* Thu Sep 30 1999 Stelian Pop +- dump 0.4b6 released, first packaging. + +* Fri Sep 10 1999 Jeff Johnson +- recompile with e2fsprogs = 1.15 (#4962). + +* Sat Jul 31 1999 Jeff Johnson +- workaround egcs bug (#4281) that caused dump problems (#2989). +- use sigjmp_buf, not jmp_buf (#3260). +- invoke /etc/rmt (instead of rmt) like other unices. (#3272). +- use glibc21 err/glob rather than the internal compatibility routines. +- wire $(OPT) throughout Makefile's. +- fix many printf problems, mostly lint clean. +- merge SuSE, Debian and many OpenBSD fixes. + +* Thu Mar 25 1999 Jeff Johnson +- remove setuid/setgid bits from /sbin/rmt (dump/restore are OK). + +* Sun Mar 21 1999 Cristian Gafton +- auto rebuild in the new build environment (release 6) + +* Fri Mar 19 1999 Jeff Johnson +- strip binaries. + +* Thu Mar 18 1999 Jeff Johnson +- Fix dangling symlinks (#1551). + +* Wed Mar 17 1999 Michael Maher +- Top O' the morning, build root's fixed for man pages. + +* Fri Feb 19 1999 Preston Brown +- upgraded to dump 0.4b4, massaged patches. + +* Tue Feb 02 1999 Ian A Cameron +- added patch from Derrick J Brashear for traverse.c to stop bread errors + +* Wed Jan 20 1999 Jeff Johnson +- restore original 6755 root.tty to dump/restore, defattr did tty->root (#684). +- mark /etc/dumpdates as noreplace. + +* Tue Jul 14 1998 Jeff Johnson +- add build root. + +* Tue May 05 1998 Prospector System +- translations modified for de, fr, tr + +* Thu Apr 30 1998 Cristian Gafton +- added a patch for resolving linux/types.h and sys/types.h conflicts + +* Wed Dec 31 1997 Erik Troan +- added prototype of llseek() so dump would work on large partitions + +* Thu Oct 30 1997 Donnie Barnes +- made all symlinks relative instead of absolute + +* Thu Jul 10 1997 Erik Troan +- built against glibc + +* Thu Mar 06 1997 Michael K. Johnson +- Moved rmt to its own package. + +* Tue Feb 11 1997 Michael Fulbright +- Added endian cleanups for SPARC + +* Fri Feb 07 1997 Michael K. Johnson +- Made /etc/dumpdates writeable by group disk. diff --git a/dump/Makefile.in b/dump/Makefile.in new file mode 100644 index 0000000..f18c01e --- /dev/null +++ b/dump/Makefile.in @@ -0,0 +1,55 @@ +# $Id: Makefile.in,v 1.12 2004/07/05 15:02:36 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= .. + +@MCONFIG@ + +INC= -I$(top_srcdir)/dump +ALL_CFLAGS= @CPPFLAGS@ @CFLAGS@ @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) @DUMPDEBUG@ +ALL_LDFLAGS= @LDFLAGS@ @LDOPTS@ @STATIC@ +LIBS= $(GLIBS) @ZLIB@ @BZLIB@ @BLKID@ +DEPLIBS= ../compat/lib/libcompat.a + +PROG= dump +RPROG= rdump +LINKS= ${SBINDIR}/dump ${SBINDIR}/rdump +SRCS= itime.c main.c optr.c tape.c traverse.c unctime.c +OBJS= itime.o main.o optr.o tape.o traverse.o unctime.o \ + ../common/dumprmt.o +MAN8= dump.8 +RMAN8= rdump.8 + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +all:: $(PROG) $(MAN8) + +$(PROG): $(OBJS) $(DEPLIBS) + $(LD) $(ALL_LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +$(MAN8): dump.8.in + sed -e "s|__DUMPDATES__|$(DUMPDATESPATH)|g" \ + -e "s|__DATE__|$(DATE)|g" \ + -e "s|__VERSION__|$(VERSION)|g" $< > $@ + +install:: all + $(INSTALL) -d $(SBINDIR) $(MANDIR) + $(INSTALLBIN) $(PROG) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MANDIR) + cd $(SBINDIR) && $(RM) -f $(RPROG) && $(LN_S) $(PROG) $(RPROG) + cd $(MANDIR) && $(RM) -f $(RMAN8) && $(LN_S) $(MAN8) $(RMAN8) + +clean:: + $(RM) -f $(PROG) $(MAN8) \#* *.s *.o *.a *~ core + +distclean:: clean + $(RM) -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/dump/dump.8.in b/dump/dump.8.in new file mode 100644 index 0000000..487302d --- /dev/null +++ b/dump/dump.8.in @@ -0,0 +1,660 @@ +.\" Copyright (c) 1980, 1991, 1993 +.\" Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: dump.8.in,v 1.56 2004/04/21 08:55:48 stelian Exp $ +.\" +.TH DUMP 8 "version __VERSION__ of __DATE__" BSD "System management commands" +.SH NAME +dump \- ext2/3 filesystem backup +.SH SYNOPSIS +.B dump +[\fB\-\fIlevel#\fR] +[\fB\-ackMnqSuv] +[\fB\-A \fIfile\fR] +[\fB\-B \fIrecords\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-d \fIdensity\fR] +[\fB\-D \fIfile\fR] +[\fB\-e \fIinode numbers\fR] +[\fB\-E \fIfile\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-h \fIlevel\fR] +[\fB\-I \fInr errors\fR] +[\fB\-j\fIcompression level\fR] +[\fB\-L \fIlabel\fR] +[\fB\-Q \fIfile\fR] +[\fB\-s \fIfeet\fR] +[\fB\-T \fIdate\fR] +[\fB\-y\fR] +[\fB\-z\fIcompression level\fR] +.I files-to-dump +.PP +.B dump +[\fB\-W \fR| \fB\-w\fR] +.PP +(The 4.3BSD option syntax is implemented for backward compatibility but is not +documented here.) +.SH DESCRIPTION +.B Dump +examines files on an ext2/3 filesystem and determines which files need to be +backed up. These files are copied to the given disk, tape or other storage +medium for safe keeping (see the +.B \-f +option below for doing remote backups). A dump that is larger than the output +medium is broken into multiple volumes. On most media the size is determined by +writing until an end-of-media indication is returned. +.PP +On media that cannot reliably return an end-of-media indication (such as some +cartridge tape drives), each volume is of a fixed size; the actual size is +determined by specifying cartridge media, or via the tape size, density and/or +block count options below. By default, the same output file name is used for +each volume after prompting the operator to change media. +.PP +.I files-to-dump +is either a mountpoint of a filesystem or a list of files and directories to be +backed up as a subset of a filesystem. In the former case, either the path to a +mounted filesystem or the device of an unmounted filesystem can be used. In the +latter case, certain restrictions are placed on the backup: +.B \-u +is not allowed, the only dump level that is supported is +.B 0 +and all the files and directories must reside on the same filesystem. +.SH OPTIONS +The following options are supported by +.B dump: +.TP +.BI \-level# +The dump level (any integer). A level 0, full backup, guarantees the +entire file system is copied (but see also the +.B \-h +option below). A level number above 0, incremental backup, tells +.B dump +to +copy all files new or modified since the last dump of a lower level. The +default level is 9. Historically only levels 0 to 9 were usable in +dump, this version is able to understand any integer as a dump level. +.TP +.BI \-a +\*(lqauto-size\*(rq. Bypass all tape length calculations, and write until an +end-of-media indication is returned. This works best for most modern tape +drives, and is the default. Use of this option is particularly recommended when +appending to an existing tape, or using a tape drive with hardware compression +(where you can never be sure about the compression ratio). +.TP +.BI \-A " archive_file" +Archive a dump table-of-contents in the specified +.I archive_file +to be used by +.BR restore (8) +to determine whether a file is in the dump file that is being restored. +.TP +.BI \-b " blocksize" +The number of kilobytes per dump record. The default blocksize is 10, +unless the +.B \-d +option has been used to specify a tape density of 6250BPI or more, +in which case the default blocksize is 32. Th maximal value is 1024. +Note however that, since the IO system slices all requests into chunks +of +.B MAXBSIZE +(which can be as low as 64kB), you can experience problems with +.BR dump (8) +and +.BR restore (8) +when using a higher value, depending on your kernel and/or libC versions. +.TP +.BI \-B " records" +The number of 1 kB blocks per volume. Not normally required, as +.B dump +can detect end-of-media. When the specified size is reached, +.B dump +waits for you to change the volume. This option overrides the calculation of +tape size based on length and density. If compression is on this limits the +size of the compressed output per volume. Multiple values may be given +as a single argument separated by commas. Each value will be used for one +dump volume in the order listed; if +.B dump +creates more volumes than the +number of values given, the last value will be used for the remaining +volumes. This is useful for filling up already partially filled media +(and then continuing with full size volumes on empty media) or mixing media +of different sizes. +.TP +.BI \-c +Change the defaults for use with a cartridge tape drive, with a density of 8000 +bpi, and a length of 1700 feet. Specifying a cartridge drive overrides the +end-of-media detection. +.TP +.BI \-d " density" +Set tape density to +.IR density . +The default is 1600BPI. Specifying a tape density overrides the end-of-media +detection. +.TP +.BI \-D " file" +Set the path name of the file storing the information about the previous +full and incremental dumps. The default location is +.IR __DUMPDATES__ . +.TP +.BI \-e " inodes" +Exclude +.I inodes +from the dump. The +.I inodes +parameter is a comma separated list of inode numbers (you can use +.BR stat (1) +to find the inode number for a file or directory). +.TP +.BI \-E " file" +Read list of inodes to be excluded from the dump from the text file +.IR file . +The file +.I file +should be an ordinary file containing inode numbers separated by newlines. +.TP +.BI \-f " file" +Write the backup to +.IR file ; +.I file +may be a special device file like +.I /dev/st0 +(a tape drive), +.I /dev/rsd1c +(a floppy disk drive), an ordinary file, or +.I \- +(the standard output). Multiple file names may be given as a single argument +separated by commas. Each file will be used for one dump volume in the order +listed; if the dump requires more volumes than the number of names given, +the last file name will used for all remaining volumes after prompting for +media changes. If the name of the file is of the form +.I host:file +or +.I user@host:file +.B dump +writes to the named file on the remote host (which should already +exist, dump doesn't create a new remote file) using +.BR rmt (8). +The default path name of the remote +.BR rmt (8) +program is +.IR /etc/rmt ; +this can be overridden by the environment variable +.BR RMT . +.TP +.BI \-F " script" +Run script at the end of each tape (except for the last one). +The device name and the current volume number are passed on the +command line. The script must return 0 if +.B dump +should continue without asking the user to change the tape, 1 if +.B dump +should continue but ask the user to change the tape. Any other exit code will +cause +.B dump +to abort. For security reasons, +.B dump +reverts back to the real user ID and the real group ID before running the +script. +.TP +.BI \-h " level" +Honor the user +.B nodump +flag +.B UF_NODUMP +only for dumps at or above the given +.IR level . +The default honor level is 1, so that incremental backups omit such files but +full backups retain them. +.TP +.BI \-I " nr errors" +By default, +.B dump +will ignore the first 32 read errors on the file system before asking for +operator intervention. You can change this using this flag to any value. This +is useful when running +.B dump +on an active filesystem where read errors simply indicate an inconsistency +between the mapping and dumping passes. +.IP +A value of 0 means that all read errors will be ignored. +.TP +.BI \-j "compression level" +Compress every block to be written on the tape using bzlib library. This option +will work only when dumping to a file or pipe or, when dumping to a tape drive, +if the tape drive is capable of writing variable length blocks. You will need +at least the 0.4b24 version of +.B restore +in order to extract compressed tapes. Tapes written using compression will not +be compatible with the BSD tape format. The (optional) parameter specifies the +compression level bzlib will use. The default compression level is 2. If the +optional parameter is specified, there should be no white space between the +option letter and the parameter. +.TP +.BI \-k +Use Kerberos authentication to talk to remote tape servers. (Only available if +this option was enabled when +.B dump +was compiled.) +.TP +.BI \-L " label" +The user-supplied text string +.I label +is placed into the dump header, where tools like +.BR restore (8) +and +.BR file (8) +can access it. Note that this label is limited to be at most +.B LBLSIZE +(currently 16) characters, which must include the terminating \e0. +.TP +.BI \-m +If this flag is specified, +.B dump +will optimise the output for inodes having been changed but not modified since +the last dump ('changed' and 'modified' have the meaning defined in +.BR stat (2) +). For those inodes, +.B dump +will save only the metadata, instead of saving the entire inode contents. +Inodes which are either directories or have been modified since the last dump +are saved in a regular way. Uses of this flag must be consistent, meaning that +either every dump in an incremental dump set have the flag, or no one has it. +.IP +Tapes written using such 'metadata only' inodes will not be compatible with the +BSD tape format or older versions of +.B restore. +.TP +.BI \-M +Enable the multi-volume feature. The name specified with +.B f +is treated as a prefix and +.B dump +writes in sequence to +.I 001, 002 +etc. This can be useful when dumping to files on an ext2 partition, in order to +bypass the 2GB file size limitation. +.TP +.BI \-n +Whenever +.B dump +requires operator attention, notify all operators in the group +.B operator +by means similar to a +.BR wall (1). +.TP +.BI \-q +Make +.B dump +abort immediately whenever operator attention is required, without prompting in +case of write errors, tape changes etc. +.TP +.BI \-Q " file" +Enable the Quick File Access support. Tape positions for each inode are stored +into the file +.I file +which is used by +.B restore +(if called with parameter +.B \-Q +and the filename) to directly position the tape at the file +.B restore +is currently working on. This saves hours when restoring single files from +large backups, saves the tapes and the drive's head. +.IP +It is recommended to set up the st driver to return logical tape positions +rather than physical before calling +.B dump/restore +with parameter +.BR \-Q . +Since not all tape devices support physical tape positions those tape devices +return an error during +.B dump/restore +when the st driver is set to the default physical setting. Please see the +.BR st (4) +man page, option +.B MTSETDRVBUFFER +, or the +.BR mt (1) +man page, on how to set the driver to return logical tape positions. +.IP +Before calling +.B restore +with parameter +.BR \-Q , +always make sure the st driver is set to return the same type of tape position +used during the call to +.BR dump . +Otherwise +.B restore +may be confused. +.IP +This option can be used when dumping to local tapes (see above) or to local +files. +.TP +.BI \-s " feet" +Attempt to calculate the amount of tape needed at a particular density. If this +amount is exceeded, +.B dump +prompts for a new tape. It is recommended to be a bit conservative on this +option. The default tape length is 2300 feet. Specifying the tape size +overrides end-of-media detection. +.TP +.BI \-S +Size estimate. Determine the amount of space that is needed to perform the dump +without actually doing it, and display the estimated number of bytes it will +take. This is useful with incremental dumps to determine how many volumes of +media will be needed. +.TP +.BI \-T " date" +Use the specified date as the starting time for the dump instead of the time +determined from looking in +.I __DUMPDATES__ . +The format of +.I date +is the same as that of +.BR ctime (3) +followed by an rfc822 timezone specification: either a plus or minus sign +followed by two digits for the number of hours and two digits for the minutes. +For example, -0800 for eight hours west of Greenwich or +0230 for two hours +and a half east of Greenwich. This timezone offset takes into account +daylight savings time (if applicable to the timezone): UTC offsets +when daylight savings time is in effect will be different than offsets +when daylight savings time is not in effect. For backward +compatibility, if no timezone is specified, a local time is assumed. +This option is useful for automated dump scripts that wish to dump over a +specific period of time. The +.B \-T +option is mutually exclusive from the +.B \-u +option. +.TP +.BI \-u +Update the file +.I __DUMPDATES__ +after a successful dump. The format of +.I __DUMPDATES__ +is readable by people, consisting of one free format record per line: +filesystem name, increment level and +.BR ctime (3) +format dump date followed by a rfc822 timezone specification (see the +.B \-u +option for details). If no timezone offset is specified, times are interpreted +as local. Whenever the file is written, all dates in the file are converted +to the local time zone, without changing the UTC times. There +may be only one entry per filesystem at each level. The file +.I __DUMPDATES__ +may be edited to change any of the fields, if necessary. +.TP +.BI \-v +The +.B \-v +(verbose) makes +.B dump +to print extra information which could be helpful in debug sessions. +.TP +.BI \-W +.B Dump +tells the operator what file systems need to be dumped. This information is +gleaned from the files +.I __DUMPDATES__ +and +.IR /etc/fstab . +The +.B \-W +option causes +.B dump +to print out, for all file systems in +.I __DUMPDATES__ , +and regognized file systems in +.I /etc/mtab +and +.IR /etc/fstab . +the most recent dump date and level, and highlights those that should be +dumped. If the +.B \-W +option is set, all other options are ignored, and +.B dump +exits immediately. +.TP +.BI \-w +Is like +.BR \-W , +but prints only recognized filesystems in +.I /etc/mtab +and +.I /etc/fstab +which need to be dumped. +.TP +.BI \-y +Compress every block to be written to the tape using the lzo library. +This doesn't compress as well as the zlib library but it's much faster. +This option will work only when dumping to a file or pipe or, when dumping to +a tape drive, if the tape drive is capable of writing variable length blocks. +You will need at least the 0.4b34 version of +.B restore +in order to extract compressed tapes. Tapes written using compression will not +be compatible with the BSD tape format. +.TP +.BI \-z "compression level" +Compress every block to be written on the tape using zlib library. This option +will work only when dumping to a file or pipe or, when dumping to a tape drive, +if the tape drive is capable of writing variable length blocks. You will need +at least the 0.4b22 version of +.B restore +in order to extract compressed tapes. Tapes written using compression will not +be compatible with the BSD tape format. The (optional) parameter specifies the +compression level zlib will use. The default compression level is 2. If the +optional parameter is specified, there should be no white space between the +option letter and the parameter. +.PP +.B Dump +requires operator intervention on these conditions: end of tape, end of dump, +tape write error, tape open error or disk read error (if there is more than a +threshold of nr errors). In addition to alerting all operators implied by the +.B \-n +key, +.B dump +interacts with the operator on dump's control terminal at times when +.B dump +can no longer proceed, or if something is grossly wrong. All questions +.B dump +poses +.I must +be answered by typing \*(lqyes\*(rq or \*(lqno\*(rq, appropriately. +.PP +Since making a dump involves a lot of time and effort for full dumps, +.B dump +checkpoints itself at the start of each tape volume. If writing that volume +fails for some reason, +.B dump +will, with operator permission, restart itself from the checkpoint after the +old tape has been rewound and removed, and a new tape has been mounted. +.PP +.B Dump +tells the operator what is going on at periodic intervals, including usually +low estimates of the number of blocks to write, the number of tapes it will +take, the time to completion, and the time to the tape change. The output is +verbose, so that others know that the terminal controlling +.B dump +is busy, and will be for some time. +.PP +In the event of a catastrophic disk event, the time required to restore all the +necessary backup tapes or files to disk can be kept to a minimum by staggering +the incremental dumps. An efficient method of staggering incremental dumps to +minimize the number of tapes follows: +.IP \(em +Always start with a level 0 backup, for example: +.RS 14 +.B /sbin/dump -0u -f /dev/st0 /usr/src +.RE +.IP +This should be done at set intervals, say once a month or once every two months, +and on a set of fresh tapes that is saved forever. +.IP \(em +After a level 0, dumps of active file systems are taken on a daily basis, using +a modified Tower of Hanoi algorithm, with this sequence of dump levels: +.RS 14 +.B 3 2 5 4 7 6 9 8 9 9 ... +.RE +.IP +For the daily dumps, it should be possible to use a fixed number of tapes for +each day, used on a weekly basis. Each week, a level 1 dump is taken, and the +daily Hanoi sequence repeats beginning with 3. For weekly dumps, another fixed +set of tapes per dumped file system is used, also on a cyclical basis. +.PP +After several months or so, the daily and weekly tapes should get rotated out +of the dump cycle and fresh tapes brought in. +.SH ENVIRONMENT +.TP +.B TAPE +If no +.B \-f +option was specified, +.B dump +will use the device specified via +.B TAPE +as the dump device. +.B TAPE +may be of the form +.IR tapename , +.IR host:tapename , +or +.IR user@host:tapename . +.TP +.B RMT +The environment variable +.B RMT +will be used to determine the pathname of the remote +.BR rmt (8) +program. +.TP +.B RSH +.B Dump +uses the contents of this variable to determine the name of the remote shell +command to use when doing remote backups (rsh, ssh etc.). If this variable is +not set, +.BR rcmd (3) +will be used, but only root will be able to do remote backups. +.SH FILES +.TP +.I /dev/st0 +default tape unit to dump to +.TP +.I __DUMPDATES__ +dump date records +.TP +.I /etc/fstab +dump table: file systems and frequency +.TP +.I /etc/mtab +dump table: mounted file systems +.TP +.I /etc/group +to find group +.I operator +.SH SEE ALSO +.BR fstab (5), +.BR restore (8), +.BR rmt (8) +.SH DIAGNOSTICS +Many, and verbose. +.SH COMPATIBILITY +The format of the +.I __DUMPDATES__ +file has changed in release 0.4b34, however, the file will be read +correctly with either pre-0.4b34 or 0.4b34 and later versions of +.B dump +provided that the machine on which +.B dump +is run did not change timezones (which should be a fairly rare occurence). +.SH EXIT STATUS +.B Dump +exits with zero status on success. Startup errors are indicated with an exit +code of 1; abnormal termination is indicated with an exit code of 3. +.SH BUGS +It might be considered a bug that this version of dump can only handle ext2/3 +filesystems. Specifically, it does not work with FAT filesystems. +.PP +Fewer than 32 read errors (change this with +.BR \-I ) +on the filesystem are ignored. If noticing read errors is important, the output +from dump can be parsed to look for lines that contain the text 'read error'. +.PP +When a read error occurs, +.B dump +prints out the corresponding physical disk block and sector number and the +ext2/3 logical block number. It doesn't print out the corresponing file name or +even the inode number. The user has to use +.BR debugfs (8), +commands +.B ncheck +and +.B icheck +to translate the +.B ext2blk +number printed out by +.B dump +into an inode number, then into a file name. +.PP +Each reel requires a new process, so parent processes for reels already written +just hang around until the entire tape is written. +.PP +The estimated number of tapes is not correct if compression is on. +.PP +It would be nice if +.B dump +knew about the dump sequence, kept track of the tapes scribbled on, told the +operator which tape to mount when, and provided more assistance for the +operator running +.BR restore . +.PP +.B Dump +cannot do remote backups without being run as root, due to its security history. +Presently, it works if you set it setuid (like it used to be), but this might +constitute a security risk. Note that you can set +.B RSH +to use a remote shell program instead. +.SH AUTHOR +The +.B dump/restore +backup suite was ported to Linux's Second Extended File System by Remy Card +. He maintained the initial versions of +.B dump +(up and including 0.4b4, released in january 1997). +.PP +Starting with 0.4b5, the new maintainer is Stelian Pop . +.SH AVAILABILITY +The +.B dump/restore +backup suite is available from +.SH HISTORY +A +.B dump +command appeared in +.B Version 6 AT&T UNIX. diff --git a/dump/dump.h b/dump/dump.h new file mode 100644 index 0000000..fafd4c3 --- /dev/null +++ b/dump/dump.h @@ -0,0 +1,289 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: dump.h,v 1.49 2004/07/01 09:14:49 stelian Exp $ + */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) +#define MAXNINDIR (MAXBSIZE / sizeof(blk_t)) +#define NUM_STR_SIZE 32 /* a generic number buffer size */ + +/* + * Dump maps used to describe what is to be dumped. + */ +extern int mapsize; /* size of the state maps */ +extern char *usedinomap; /* map of allocated inodes */ +extern char *dumpdirmap; /* map of directories to be dumped */ +extern char *dumpinomap; /* map of files to be dumped */ +extern char *metainomap; /* which of the inodes in dumpinomap + will get only their metadata dumped */ +/* + * Map manipulation macros. + */ +#define SETINO(ino, map) \ + map[(u_int)((ino) - 1) / NBBY] |= 1 << ((u_int)((ino) - 1) % NBBY) +#define CLRINO(ino, map) \ + map[(u_int)((ino) - 1) / NBBY] &= ~(1 << ((u_int)((ino) - 1) % NBBY)) +#define TSTINO(ino, map) \ + (map[(u_int)((ino) - 1) / NBBY] & (1 << ((u_int)((ino) - 1) % NBBY))) + +/* + * All calculations done in 0.1" units! + */ +extern char *host; /* name of the remote host */ +extern const char *disk; /* name of the disk file */ +extern char tape[MAXPATHLEN];/* name of the tape file */ +extern char *tapeprefix; /* prefix of the tape file */ +extern char *dumpdates; /* name of the file containing dump date information*/ +extern char lastlevel[NUM_STR_SIZE];/* dump level of previous dump */ +extern char level[NUM_STR_SIZE];/* dump level of this dump */ +extern int Afile; /* archive file descriptor */ +extern int AfileActive; /* Afile flag */ +extern int zipflag; /* which compression method */ +extern int uflag; /* update flag */ +extern int mflag; /* dump metadata only if possible flag */ +extern int Mflag; /* multi-volume flag */ +extern int qflag; /* quit on errors flag */ +extern int vflag; /* verbose flag */ +extern int breademax; /* maximum number of bread errors before we quit */ +extern char *eot_script; /* end of volume script fiag */ +extern int diskfd; /* disk file descriptor */ +extern int tapefd; /* tape file descriptor */ +extern int pipeout; /* true => output to standard output */ +extern int fifoout; /* true => output to fifo */ +extern dump_ino_t curino; /* current inumber; used globally */ +extern int newtape; /* new tape flag */ +extern int density; /* density in 0.1" units */ +extern long tapesize; /* estimated tape size, blocks */ +extern long tsize; /* tape size in 0.1" units */ +extern long asize; /* number of 0.1" units written on current tape */ +extern int etapes; /* estimated number of tapes */ +extern int nonodump; /* if set, do not honor UF_NODUMP user flags */ +extern int unlimited; /* if set, write to end of medium */ +extern int compressed; /* if set, dump is to be compressed */ +extern long long bytes_written;/* total bytes written to tape */ +extern long uncomprblks; /* uncompressed blocks written to tape */ +extern int notify; /* notify operator flag */ +extern int blockswritten; /* number of blocks written on current tape */ +extern int tapeno; /* current tape number */ +extern time_t tstart_writing; /* when started writing the first tape block */ +extern time_t tend_writing; /* after writing the last tape block */ +#ifdef __linux__ +extern ext2_filsys fs; +#else +extern struct fs *sblock; /* the file system super block */ +extern char sblock_buf[MAXBSIZE]; +#endif +extern long xferrate; /* averaged transfer rate of all volumes */ +extern long dev_bsize; /* block size of underlying disk device */ +extern int dev_bshift; /* log2(dev_bsize) */ +extern int tp_bshift; /* log2(TP_BSIZE) */ +extern dump_ino_t volinfo[]; /* which inode on which volume archive info */ + +#ifdef USE_QFA +#define QFA_MAGIC "495115637697" +#define QFA_VERSION "1.0" +extern int gTapeposfd; +extern char *gTapeposfile; +extern char gTps[255]; +extern int32_t gThisDumpDate; +#endif /* USE_QFA */ + +#ifndef __P +#include +#endif + +/* operator interface functions */ +void broadcast __P((const char *message)); +time_t do_stats __P((void)); +void lastdump __P((char arg)); +void msg __P((const char *fmt, ...)); +void msgtail __P((const char *fmt, ...)); +int query __P((const char *question)); +void quit __P((const char *fmt, ...)); +void set_operators __P((void)); +#if defined(SIGINFO) +void statussig __P((int signo)); +#endif +void timeest __P((void)); +time_t unctime __P((const char *str)); + +/* mapping rouintes */ +struct dinode; +long blockest __P((struct dinode const *dp)); +int mapfiles __P((dump_ino_t maxino, long *tapesize)); +#ifdef __linux__ +int mapfilesfromdir __P((dump_ino_t maxino, long *tapesize, char *directory)); +int maponefile __P((dump_ino_t maxino, long *tapesize, char *directory)); +#endif +int mapdirs __P((dump_ino_t maxino, long *tapesize)); + +/* file dumping routines */ +void blksout __P((blk_t *blkp, int frags, dump_ino_t ino)); +void bread __P((ext2_loff_t blkno, char *buf, int size)); +void dumpino __P((struct dinode *dp, dump_ino_t ino, int metaonly)); +#ifdef __linux__ +void dumpdirino __P((struct dinode *dp, dump_ino_t ino)); +#endif +void dumpmap __P((char *map, int type, dump_ino_t ino)); +void writeheader __P((dump_ino_t ino)); +void mkchecksum __P((union u_spcl *tmpspcl)); + +/* tape writing routines */ +int alloctape __P((void)); +void close_rewind __P((void)); +void dumpblock __P((blk_t blkno, int size)); +void startnewtape __P((int top)); +time_t trewind __P((void)); +void writerec __P((const void *dp, int isspcl)); +char *mktimeest __P((time_t tnow)); + +void Exit __P((int status)); +void dumpabort __P((int signo)); +void getfstab __P((void)); + +const char *rawname __P((const char *cp)); +struct dinode *getino __P((dump_ino_t inum)); + +/* rdump routines */ +#ifdef RDUMP +int rmthost __P((const char *host)); +int rmtopen __P((const char *tape, const int mode)); +void rmtclose __P((void)); +int rmtread __P((char *buf, size_t count)); +int rmtwrite __P((const char *buf, size_t count)); +OFF_T rmtseek __P((OFF_T offset, int pos)); +struct mtget * rmtstatus __P((void)); +int rmtioctl __P((int cmd, int count)); +#endif /* RDUMP */ + +void interrupt __P((int signo)); /* in case operator bangs on console */ +int exclude_ino __P((dump_ino_t ino)); +void do_exclude_ino __P((dump_ino_t ino, const char *)); + +/* + * Exit status codes + */ +#define X_FINOK 0 /* normal exit */ +#define X_STARTUP 1 /* startup error */ +#define X_REWRITE 2 /* restart writing from the check point */ +#define X_ABORT 3 /* abort dump; don't attempt checkpointing */ + +#define OPGRENT "operator" /* group entry to notify */ +#ifdef __linux__ +#define DIALUP "ttyS" /* prefix for dialups */ +#else +#define DIALUP "ttyd" /* prefix for dialups */ +#endif + +#include + +struct mntent *fstabsearch __P((const char *key)); /* search fs_file and fs_spec */ +#ifdef __linux__ +struct mntent *fstabsearchdir __P((const char *key, char *dir)); /* search fs_file and fs_spec */ +#endif + +/* + * The contents of the file _PATH_DUMPDATES is maintained both on + * a linked list, and then (eventually) arrayified. + */ +struct dumpdates { + char dd_name[MAXPATHLEN+3]; + struct mntent *dd_fstab; + int dd_level; + time_t dd_ddate; +}; +struct dumptime { + struct dumpdates dt_value; + struct dumptime *dt_next; +}; +extern struct dumptime *dthead; /* head of the list version */ +extern int nddates; /* number of records (might be zero) */ +extern int ddates_in; /* we have read the increment file */ +extern struct dumpdates **ddatev; /* the arrayfied version */ +void initdumptimes __P((int)); +void getdumptime __P((int)); +void putdumptime __P((void)); +#define ITITERATE(i, ddp) \ + for (ddp = ddatev[i = 0]; i < nddates; ddp = ddatev[++i]) + +void sig __P((int signo)); + +/* + * Compatibility with old systems. + */ +#ifdef COMPAT +#include +#define strchr(a,b) index(a,b) +#define strrchr(a,b) rindex(a,b) +extern char *strdup(), *ctime(); +extern int read(), write(); +extern int errno; +#endif + +#ifdef __linux__ +#define DUMP_CURRENT_REV 1 + +int dump_fs_open(const char *disk, ext2_filsys *fs); +#endif + +#ifndef __linux__ +#ifndef _PATH_UTMP +#define _PATH_UTMP "/etc/utmp" +#endif +#ifndef _PATH_FSTAB +#define _PATH_FSTAB "/etc/fstab" +#endif +#endif + +#ifdef sunos +extern char *calloc(); +extern char *malloc(); +extern long atol(); +extern char *strcpy(); +extern char *strncpy(); +extern char *strcat(); +extern time_t time(); +extern void endgrent(); +extern void exit(); +extern off_t lseek(); +extern const char *strerror(); +#endif + diff --git a/dump/itime.c b/dump/itime.c new file mode 100644 index 0000000..f2cc763 --- /dev/null +++ b/dump/itime.c @@ -0,0 +1,328 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: itime.c,v 1.28 2004/06/17 09:01:15 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#endif + +#include +#include +#include +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#include +#elif defined sunos +#include + +#include +#include +#include +#else +#include +#endif + +#include + +#include "dump.h" + +struct dumpdates **ddatev; +int nddates; +int ddates_in; +struct dumptime *dthead; + +static void dumprecout __P((FILE *, struct dumpdates *)); +static int getrecord __P((FILE *, struct dumpdates *)); +static int makedumpdate __P((struct dumpdates *, char *)); +static void readdumptimes __P((FILE *)); + +void +initdumptimes(int createdumpdates) +{ + FILE *df; + struct flock lock; + + if ((df = fopen(dumpdates, "r")) == NULL) { + if (errno != ENOENT) { + quit("cannot read %s: %s\n", dumpdates, + strerror(errno)); + /* NOTREACHED */ + } + if (createdumpdates) { + /* + * Dumpdates does not exist, make an empty one. + */ + msg("WARNING: no file `%s', making an empty one\n", dumpdates); + if ((df = fopen(dumpdates, "w")) == NULL) { + quit("cannot create %s: %s\n", dumpdates, + strerror(errno)); + /* NOTREACHED */ + } + (void) fclose(df); + if ((df = fopen(dumpdates, "r")) == NULL) { + quit("cannot read %s even after creating it: %s\n", + dumpdates, strerror(errno)); + /* NOTREACHED */ + } + } + else + msg("WARNING: no file `%s'\n", dumpdates); + } + if (df != NULL) { + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_RDLCK; + if (fcntl(fileno(df), F_SETLKW, &lock) < 0) + quit("cannot set read lock on %s: %s\n", + dumpdates, strerror(errno)); + readdumptimes(df); + (void) fclose(df); + } +} + +static void +readdumptimes(FILE *df) +{ + int i; + struct dumptime *dtwalk; + + for (;;) { + dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); + if (getrecord(df, &(dtwalk->dt_value)) < 0) + break; + nddates++; + dtwalk->dt_next = dthead; + dthead = dtwalk; + } + + ddates_in = 1; + /* + * arrayify the list, leaving enough room for the additional + * record that we may have to add to the ddate structure + */ + ddatev = (struct dumpdates **) + calloc((unsigned) (nddates + 1), sizeof (struct dumpdates *)); + dtwalk = dthead; + for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) + ddatev[i] = &dtwalk->dt_value; +} + +void +getdumptime(int createdumpdates) +{ + struct dumpdates *ddp; + int i; + +#ifdef FDEBUG + msg("Looking for name %s in dumpdates = %s for level = %s\n", + disk, dumpdates, level); +#endif + spcl.c_ddate = 0; + memset(&lastlevel, 0, NUM_STR_SIZE); + + /* If this is a level 0 dump, and we're not updating + dumpdates, there's no point in trying to read + dumpdates. It may not exist yet, or may not be mounted. For + incrementals, we *must* read dumpdates (fail if it's not there!) */ + if ( (!strcmp(level, lastlevel)) && !createdumpdates) + return; + initdumptimes(createdumpdates); + if (ddatev == NULL) + return; + /* + * Go find the entry with the same name for a lower increment + * and older date + */ + ITITERATE(i, ddp) { + if (strncmp(disk, ddp->dd_name, sizeof (ddp->dd_name)) != 0) + continue; + if (ddp->dd_level >= atoi(level)) + continue; + if (ddp->dd_ddate <= (time_t)spcl.c_ddate) + continue; + spcl.c_ddate = ddp->dd_ddate; + snprintf(lastlevel, NUM_STR_SIZE, "%d", ddp->dd_level); + } +} + +void +putdumptime(void) +{ + FILE *df; + struct dumpdates *dtwalk; + int i; + int fd; + struct flock lock; + + if(uflag == 0) + return; + if ((df = fopen(dumpdates, "r+")) == NULL) + quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); + fd = fileno(df); + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_WRLCK; + if (fcntl(fd, F_SETLKW, &lock) < 0) + quit("cannot set write lock on %s: %s\n", dumpdates, strerror(errno)); + free((char *)ddatev); + ddatev = 0; + nddates = 0; + dthead = 0; + ddates_in = 0; + readdumptimes(df); + if (fseek(df, 0L, 0) < 0) + quit("fseek: %s\n", strerror(errno)); + spcl.c_ddate = 0; + ITITERATE(i, dtwalk) { + if (strncmp(disk, dtwalk->dd_name, + sizeof (dtwalk->dd_name)) != 0) + continue; + if (dtwalk->dd_level != atoi(level)) + continue; + goto found; + } + /* + * construct the new upper bound; + * Enough room has been allocated. + */ + dtwalk = ddatev[nddates] = + (struct dumpdates *)calloc(1, sizeof (struct dumpdates)); + nddates += 1; + found: + (void) strncpy(dtwalk->dd_name, disk, sizeof (dtwalk->dd_name)); + dtwalk->dd_level = atoi(level); + dtwalk->dd_ddate = spcl.c_date; + + ITITERATE(i, dtwalk) { + dumprecout(df, dtwalk); + } + if (fflush(df)) + quit("%s: %s\n", dumpdates, strerror(errno)); + if (ftruncate(fd, ftell(df))) + quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); + (void) fclose(df); +} + +static void +dumprecout(FILE *file, struct dumpdates *what) +{ + char buf[26]; + struct tm *tms; + + tms = localtime(&what->dd_ddate); + strncpy(buf, asctime(tms), sizeof(buf)); + if (buf[24] != '\n' || buf[25] != '\0') + quit("asctime returned an unexpected string\n"); + buf[24] = 0; + if (fprintf(file, "%s %d %s %c%2.2d%2.2d\n", + what->dd_name, + what->dd_level, + buf, + (tms->tm_gmtoff < 0 ? '-' : '+'), + abs(tms->tm_gmtoff) / 3600, + abs(tms->tm_gmtoff) % 3600 / 60) < 0) + quit("%s: %s\n", dumpdates, strerror(errno)); +} + +int recno; + +static int +getrecord(FILE *df, struct dumpdates *ddatep) +{ + char tbuf[BUFSIZ]; + + recno = 0; + if (fgets(tbuf, sizeof (tbuf), df) == NULL) + return(-1); + recno++; + if (makedumpdate(ddatep, tbuf) < 0) { + msg("Unknown format in %s, line %d\n", + dumpdates, recno); + return(-1); + } + +#ifdef FDEBUG + msg("getrecord: %s %d %s", ddatep->dd_name, ddatep->dd_level, + ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); +#endif + return(0); +} + +static int +makedumpdate(struct dumpdates *ddp, char *tbuf) +{ + char *tok; + /* device name */ + if ( NULL == (tok = strsep( &tbuf, " ")) ) + return(-1); + if ( !tbuf || strlen(tok) > MAXPATHLEN ) + return(-1); + strcpy(ddp->dd_name, tok); + + /* eat whitespace */ + for( ; *tbuf == ' ' ; tbuf++); + + /* dump level */ + ddp->dd_level = atoi(tbuf); + /* eat the rest of the numbers*/ + for( ; *tbuf >= '0' && *tbuf <= '9' ; tbuf++); + + /* eat whitespace */ + for( ; *tbuf == ' ' ; tbuf++); + + /* dump date */ + ddp->dd_ddate = unctime(tbuf); + if (ddp->dd_ddate < 0) + return(-1); + /* fstab entry */ + ddp->dd_fstab = fstabsearch(ddp->dd_name); + return(0); +} diff --git a/dump/main.c b/dump/main.c new file mode 100644 index 0000000..b73a788 --- /dev/null +++ b/dump/main.c @@ -0,0 +1,1399 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: main.c,v 1.94 2004/07/05 15:12:45 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef __linux__ +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#include /* for definition of BLKFLSBUF */ +#elif defined sunos +#include + +#include +#include +#else +#include +#include +#endif + +#include + +#include "dump.h" +#include "pathnames.h" +#include "bylabel.h" + +#ifndef SBOFF +#define SBOFF (SBLOCK * DEV_BSIZE) +#endif + +int abortifconnerr = 1; /* set to 1 if lib dumprmt.o should exit on connection errors + otherwise just print a message using msg */ +/* + * Dump maps used to describe what is to be dumped. + */ +int mapsize; /* size of the state maps */ +char *usedinomap; /* map of allocated inodes */ +char *dumpdirmap; /* map of directories to be dumped */ +char *dumpinomap; /* map of files to be dumped */ +char *metainomap; /* which of the inodes in dumpinomap will get + only their metadata dumped */ + +const char *disk; /* name of the disk file */ +char tape[MAXPATHLEN];/* name of the tape file */ +char *tapeprefix; /* prefix of the tape file */ +char *dumpdates; /* name of the file containing dump date information*/ +char lastlevel[NUM_STR_SIZE];/* dump level of previous dump */ +char level[NUM_STR_SIZE];/* dump level of this dump */ +int zipflag; /* which compression method */ +int Afile = -1; /* archive file descriptor */ +int AfileActive = 1;/* Afile flag */ +int uflag; /* update flag */ +int mflag; /* dump metadata only if possible */ +int Mflag; /* multi-volume flag */ +int qflag; /* quit on errors flag */ +int vflag; /* verbose flag */ +int breademax = 32; /* maximum number of bread errors before we quit */ +char *eot_script; /* end of volume script fiag */ +int diskfd; /* disk file descriptor */ +int tapefd; /* tape file descriptor */ +int pipeout; /* true => output to standard output */ +int fifoout; /* true => output to fifo */ +dump_ino_t curino; /* current inumber; used globally */ +int newtape; /* new tape flag */ +int density; /* density in 0.1" units */ +long tapesize; /* estimated tape size, blocks */ +long tsize; /* tape size in 0.1" units */ +long asize; /* number of 0.1" units written on current tape */ +int etapes; /* estimated number of tapes */ +int nonodump; /* if set, do not honor UF_NODUMP user flags */ +int unlimited; /* if set, write to end of medium */ +int compressed; /* if set, dump is to be compressed */ +long long bytes_written;/* total bytes written to tape */ +long uncomprblks; /* uncompressed blocks written to tape */ +int notify; /* notify operator flag */ +int blockswritten; /* number of blocks written on current tape */ +int tapeno; /* current tape number */ +time_t tstart_writing; /* when started writing the first tape block */ +time_t tend_writing; /* after writing the last tape block */ +#ifdef __linux__ +ext2_filsys fs; +#else +struct fs *sblock; /* the file system super block */ +char sblock_buf[MAXBSIZE]; +#endif +long xferrate; /* averaged transfer rate of all volumes */ +long dev_bsize; /* block size of underlying disk device */ +int dev_bshift; /* log2(dev_bsize) */ +int tp_bshift; /* log2(TP_BSIZE) */ +dump_ino_t volinfo[TP_NINOS];/* which inode on which volume archive info */ + +#ifdef USE_QFA +int gTapeposfd; +char *gTapeposfile; +char gTps[255]; +int32_t gThisDumpDate; +#endif /* USE_QFA */ + +struct dumptime *dthead; /* head of the list version */ +int nddates; /* number of records (might be zero) */ +int ddates_in; /* we have read the increment file */ +struct dumpdates **ddatev; /* the arrayfied version */ + +int notify = 0; /* notify operator flag */ +int blockswritten = 0; /* number of blocks written on current tape */ +int tapeno = 0; /* current tape number */ +int density = 0; /* density in bytes/0.1" " <- this is for hilit19 */ +int ntrec = NTREC; /* # blocks in each tape record */ +int cartridge = 0; /* Assume non-cartridge tape */ +#ifdef USE_QFA +int tapepos = 0; /* assume no QFA tapeposition needed by user */ +#endif /* USE_QFA */ +int dokerberos = 0; /* Use Kerberos authentication */ +long dev_bsize = 1; /* recalculated below */ +long *blocksperfiles = NULL; /* output blocks per file(s) */ +char *host = NULL; /* remote host (if any) */ +int sizest = 0; /* return size estimate only */ +int compressed = 0; /* use zlib to compress the output, compress level 1-9 */ +long long bytes_written = 0; /* total bytes written */ +long uncomprblks = 0;/* uncompressed blocks written */ + +long smtc_errno; + +#ifdef __linux__ +char *__progname; +#endif + +int maxbsize = 1024*1024; /* XXX MAXBSIZE from sys/param.h */ +static long numarg __P((const char *, long, long)); +static long *numlistarg __P((const char *, long, long)); +static void obsolete __P((int *, char **[])); +static void usage __P((void)); +static void do_exclude_from_file __P((char *)); +static void do_exclude_ino_str __P((char *)); +static void incompat_flags __P((int, char, char)); + +static char* iexclude_bitmap = NULL; /* the inode exclude bitmap */ +static unsigned int iexclude_bitmap_bytes = 0; /* size of bitmap in bytes */ + +int +main(int argc, char *argv[]) +{ + dump_ino_t ino; + int dirty; + struct dinode *dp; + struct mntent *dt; + char *map; + int ch, pch = 0; + int i, anydirskipped; + int aflag = 0, bflag = 0, Tflag = 0, honorlevel = 1; + dump_ino_t maxino; + struct STAT statbuf; + dev_t filedev = 0; +#ifdef __linux__ + errcode_t retval; + char directory[MAXPATHLEN]; + char pathname[MAXPATHLEN]; +#endif + time_t tnow; + char *diskparam; + char *Apath = NULL; + + spcl.c_label[0] = '\0'; + spcl.c_date = time(NULL); + +#ifdef __linux__ + __progname = argv[0]; + directory[0] = 0; + initialize_ext2_error_table(); +#endif + + tsize = 0; /* Default later, based on 'c' option for cart tapes */ + unlimited = 1; + eot_script = NULL; + if ((tapeprefix = getenv("TAPE")) == NULL) + tapeprefix = _PATH_DEFTAPE; + dumpdates = _PATH_DUMPDATES; + if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) + quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); + memset(&lastlevel, 0, NUM_STR_SIZE); + memset(&level, 0, NUM_STR_SIZE); + + if (argc < 2) + usage(); + + obsolete(&argc, &argv); + +#ifdef USE_QFA + gTapeposfd = -1; +#endif /* USE_QFA */ + + while ((ch = getopt(argc, argv, + "0123456789A:aB:b:cd:D:e:E:f:F:h:I:" +#ifdef HAVE_BZLIB + "j::" +#endif + "L:" +#ifdef KERBEROS + "k" +#endif + "mMnq" +#ifdef USE_QFA + "Q:" +#endif + "s:ST:uvWw" +#ifdef HAVE_LZO + "y" +#endif +#ifdef HAVE_ZLIB + "z::" +#endif + )) != -1) + switch (ch) { + /* dump level */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if ((pch >= '0') && (pch <= '9') && (strlen(level) < NUM_STR_SIZE)) + level[strlen(level)] = ch; + else + level[0] = ch; + pch = ch; + break; + + case 'A': /* archive file */ + Apath = optarg; + break; + + case 'a': /* `auto-size', Write to EOM. */ + unlimited = 1; + aflag = 1; + break; + + case 'B': /* blocks per output file */ + unlimited = 0; + blocksperfiles = numlistarg("number of blocks per file", + 1L, 0L); + break; + + case 'b': /* blocks per tape write */ + ntrec = numarg("number of blocks per write", + 1L, 1048576L); + if (ntrec > maxbsize/1024) { + msg("Please choose a blocksize <= %dkB\n", + maxbsize/1024); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + bflag = 1; + break; + + case 'c': /* Tape is cart. not 9-track */ + unlimited = 0; + cartridge = 1; + break; + + case 'd': /* density, in bits per inch */ + unlimited = 0; + density = numarg("density", 10L, 327670L) / 10; + if (density >= 625 && !bflag) + ntrec = HIGHDENSITYTREC; + break; + + case 'D': /* path of dumpdates file */ + dumpdates = optarg; + break; + + /* 04-Feb-00 ILC */ + case 'e': /* exclude an inode */ + { + char *p = optarg, *q; + while ((q = strchr(p, ','))) { + *q = '\0'; + do_exclude_ino_str(p); + p = q + 1; + } + do_exclude_ino_str(p); + } + break; + + case 'E': /* exclude inodes read from file */ + do_exclude_from_file(optarg); + break; + + case 'f': /* output file */ + tapeprefix = optarg; + break; + + case 'F': /* end of tape script */ + eot_script = optarg; + break; + + case 'h': + honorlevel = numarg("honor level", 0L, 10L); + break; + +#ifdef HAVE_BZLIB + case 'j': + compressed = 2; + zipflag = COMPRESS_BZLIB; + if (optarg) + compressed = numarg("compress level", 1L, 9L); + break; +#endif /* HAVE_BZLIB */ + + case 'I': + breademax = + numarg ("number of errors to ignore", 0L, 0L); + break; + +#ifdef KERBEROS + case 'k': + dokerberos = 1; + break; +#endif + + case 'L': + /* + * Note that although there are LBLSIZE characters, + * the last must be '\0', so the limit on strlen() + * is really LBLSIZE-1. + */ + strncpy(spcl.c_label, optarg, LBLSIZE); + spcl.c_label[LBLSIZE-1] = '\0'; + if (strlen(optarg) > LBLSIZE-1) { + msg( + "WARNING Label `%s' is larger than limit of %d characters.\n", + optarg, LBLSIZE-1); + msg("WARNING: Using truncated label `%s'.\n", + spcl.c_label); + } + break; + + case 'm': /* metadata only flag */ + mflag = 1; + break; + + case 'M': /* multi-volume flag */ + Mflag = 1; + break; + + case 'n': /* notify operators */ + notify = 1; + break; + + case 'q': + qflag = 1; + break; + +#ifdef USE_QFA + case 'Q': /* create tapeposfile */ + gTapeposfile = optarg; + tapepos = 1; + break; +#endif /* USE_QFA */ + + case 's': /* tape size, feet */ + unlimited = 0; + tsize = numarg("tape size", 1L, 0L) * 12 * 10; + break; + + case 'S': + sizest = 1; /* return size estimate only */ + break; + + case 'T': /* time of last dump */ + spcl.c_ddate = unctime(optarg); + if (spcl.c_ddate < 0) { + msg("bad time \"%s\"\n", optarg); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + Tflag = 1; + lastlevel[0] = '?'; lastlevel[1] = '\0'; + break; + + case 'u': /* update dumpdates */ + uflag = 1; + break; + + case 'v': /* verbose */ + vflag = 1; + break; + + case 'W': /* what to do */ + case 'w': + lastdump(ch); + exit(X_FINOK); /* do nothing else */ +#ifdef HAVE_LZO + case 'y': + compressed = 2; + zipflag = COMPRESS_LZO; + break; +#endif /* HAVE_LZO */ + +#ifdef HAVE_ZLIB + case 'z': + compressed = 2; + zipflag = COMPRESS_ZLIB; + if (optarg) + compressed = numarg("compress level", 1L, 9L); + break; +#endif /* HAVE_ZLIB */ + + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 1) { + msg("Must specify disk or filesystem\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + diskparam = *argv++; + if (strlen(diskparam) >= MAXPATHLEN) { + msg("Disk or filesystem name too long: %s\n", diskparam); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + argc--; + incompat_flags(Tflag && uflag, 'T', 'u'); + incompat_flags(aflag && blocksperfiles, 'a', 'B'); + incompat_flags(aflag && cartridge, 'a', 'c'); + incompat_flags(aflag && density, 'a', 'd'); + incompat_flags(aflag && tsize, 'a', 's'); + + if (strcmp(tapeprefix, "-") == 0) { + pipeout++; + tapeprefix = "standard output"; + } + + if (blocksperfiles && !compressed) + for (i = 1; i <= *blocksperfiles; i++) + blocksperfiles[i] = blocksperfiles[i] / ntrec * ntrec; /* round down */ + else if (!unlimited) { + /* + * Determine how to default tape size and density + * + * density tape size + * 9-track 1600 bpi (160 bytes/.1") 2300 ft. + * 9-track 6250 bpi (625 bytes/.1") 2300 ft. + * cartridge 8000 bpi (100 bytes/.1") 1700 ft. + * (450*4 - slop) + * hilit19 hits again: " + */ + if (density == 0) + density = cartridge ? 100 : 160; + if (tsize == 0) + tsize = cartridge ? 1700L*120L : 2300L*120L; + } + + { + int i; + char *n; + + if ((n = strchr(tapeprefix, ':'))) { + for (i = 0; i < (n - tapeprefix); i++) { + if (tapeprefix[i] == '/') + break; + } + if (tapeprefix[i] != '/') { + host = tapeprefix; + tapeprefix = strchr(host, ':'); + *tapeprefix++ = '\0'; +#ifdef RDUMP + if (index(tapeprefix, '\n')) { + msg("invalid characters in tape\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + if (rmthost(host) == 0) + exit(X_STARTUP); +#else + msg("remote dump not enabled\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); +#endif + } + } + } + + (void)setuid(getuid()); /* rmthost() is the only reason to be setuid */ + if (Apath && (Afile = open(Apath, O_WRONLY|O_CREAT|O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP | S_IROTH | S_IWOTH)) < 0) { + msg("Cannot open %s for writing: %s\n", + optarg, strerror(errno)); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, sig); + if (signal(SIGTRAP, SIG_IGN) != SIG_IGN) + signal(SIGTRAP, sig); + if (signal(SIGFPE, SIG_IGN) != SIG_IGN) + signal(SIGFPE, sig); + if (signal(SIGBUS, SIG_IGN) != SIG_IGN) + signal(SIGBUS, sig); + if (signal(SIGSEGV, SIG_IGN) != SIG_IGN) + signal(SIGSEGV, sig); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, sig); + if (signal(SIGINT, interrupt) == SIG_IGN) + signal(SIGINT, SIG_IGN); +#ifdef SIGXCPU + signal(SIGXCPU, SIG_IGN); +#endif /* SIGXCPU */ +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_IGN); +#endif /* SIGXFSZ */ + + set_operators(); /* /etc/group snarfed */ + getfstab(); /* /etc/fstab snarfed */ + + /* + * disk may end in / and this can confuse + * fstabsearch. + */ + i = strlen(diskparam) - 1; + if (i > 1 && diskparam[i] == '/') + if (!(i == 6 && !strcmp(diskparam, "LABEL=/"))) + diskparam[i] = '\0'; + + disk = get_device_name(diskparam); + if (!disk) + disk = strdup(diskparam); + + /* + * disk can be either the full special file name, + * the suffix of the special file name, + * the special name missing the leading '/', + * the file system name with or without the leading '/'. + */ + if ((dt = fstabsearch(disk)) != NULL) { + /* if found then only one parameter (i.e. partition) + * is allowed */ + if (argc >= 1) { + (void)fprintf(stderr, "Unknown arguments to dump:"); + while (argc--) + (void)fprintf(stderr, " %s", *argv++); + (void)fprintf(stderr, "\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + disk = rawname(dt->mnt_fsname); + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); + (void)strncpy(spcl.c_filesys, dt->mnt_dir, NAMELEN); + } else { +#ifdef __linux__ +#ifdef HAVE_REALPATH + if (realpath(disk, pathname) == NULL) +#endif + strcpy(pathname, disk); + /* + * The argument could be now a mountpoint of + * a filesystem specified in fstab. Search for it. + */ + if ((dt = fstabsearch(pathname)) != NULL) { + disk = rawname(dt->mnt_fsname); + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); + (void)strncpy(spcl.c_filesys, dt->mnt_dir, NAMELEN); + } else { + /* + * The argument was not found in the fstab + * assume that this is a subtree and search for it + */ + dt = fstabsearchdir(pathname, directory); + if (dt != NULL) { + char name[MAXPATHLEN]; + (void)strncpy(spcl.c_dev, dt->mnt_fsname, NAMELEN); + (void)snprintf(name, sizeof(name), "%s (dir %s)", + dt->mnt_dir, directory); + (void)strncpy(spcl.c_filesys, name, NAMELEN); + disk = rawname(dt->mnt_fsname); + } else { + (void)strncpy(spcl.c_dev, disk, NAMELEN); + (void)strncpy(spcl.c_filesys, "an unlisted file system", + NAMELEN); + } + } +#else + (void)strncpy(spcl.c_dev, disk, NAMELEN); + (void)strncpy(spcl.c_filesys, "an unlisted file system", + NAMELEN); +#endif + } + + if (directory[0] != 0) { + if (atoi(level) != 0) { + msg("Only level 0 dumps are allowed on a subdirectory\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + if (uflag) { + msg("You can't update the dumpdates file when dumping a subdirectory\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + } + spcl.c_dev[NAMELEN-1] = '\0'; + spcl.c_filesys[NAMELEN-1] = '\0'; + (void)gethostname(spcl.c_host, NAMELEN); + spcl.c_host[NAMELEN-1] = '\0'; + spcl.c_level = atoi(level); + spcl.c_type = TS_TAPE; + if (!Tflag) + getdumptime(uflag); /* dumpdates snarfed */ + + if (spcl.c_ddate == 0 && spcl.c_level) { + msg("WARNING: There is no inferior level dump on this filesystem\n"); + msg("WARNING: Assuming a level 0 dump by default\n"); + level[0] = '0'; level[1] = '\0'; + spcl.c_level = 0; + } + + if (Mflag) + snprintf(tape, MAXPATHLEN, "%s%03d", tapeprefix, tapeno + 1); + else + strncpy(tape, tapeprefix, MAXPATHLEN); + tape[MAXPATHLEN - 1] = '\0'; + + if (!pipeout) { + if (STAT(tape, &statbuf) != -1) + fifoout= statbuf.st_mode & S_IFIFO; + } + + if (!sizest) { + + msg("Date of this level %s dump: %s", level, + ctime4(&spcl.c_date)); +#ifdef USE_QFA + gThisDumpDate = spcl.c_date; +#endif + if (spcl.c_ddate) + msg("Date of last level %s dump: %s", lastlevel, + ctime4(&spcl.c_ddate)); + msg("Dumping %s (%s) ", disk, spcl.c_filesys); + if (host) + msgtail("to %s on host %s\n", tape, host); + else + msgtail("to %s\n", tape); + } /* end of size estimate */ + +#ifdef __linux__ + if ((diskfd = OPEN(disk, O_RDONLY)) < 0) { + msg("Cannot open %s\n", disk); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } +#ifdef BLKFLSBUF + (void)ioctl(diskfd, BLKFLSBUF, 0); +#endif + retval = dump_fs_open(disk, &fs); + if (retval) { + com_err(disk, retval, "while opening filesystem"); + if (retval == EXT2_ET_REV_TOO_HIGH) + msg("Get a newer version of dump!\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + if (fs->super->s_rev_level > DUMP_CURRENT_REV) { + com_err(disk, retval, "while opening filesystem"); + msg("Get a newer version of dump!\n"); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + /* if no user label specified, use ext2 filesystem label if available */ + if (spcl.c_label[0] == '\0') { + const char *lbl; + if ( (lbl = get_device_label(disk)) != NULL) { + strncpy(spcl.c_label, lbl, LBLSIZE); + spcl.c_label[LBLSIZE-1] = '\0'; + } + else + strcpy(spcl.c_label, "none"); /* safe strcpy. */ + } + sync(); + dev_bsize = DEV_BSIZE; + dev_bshift = ffs(dev_bsize) - 1; + if (dev_bsize != (1 << dev_bshift)) + quit("dev_bsize (%d) is not a power of 2", dev_bsize); + tp_bshift = ffs(TP_BSIZE) - 1; + if (TP_BSIZE != (1 << tp_bshift)) + quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); + maxino = fs->super->s_inodes_count + 1; + spcl.c_flags |= DR_NEWINODEFMT; +#else /* __linux __*/ + if ((diskfd = open(disk, O_RDONLY)) < 0) { + msg("Cannot open %s\n", disk); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + sync(); + sblock = (struct fs *)sblock_buf; + bread(SBOFF, (char *) sblock, SBSIZE); + if (sblock->fs_magic != FS_MAGIC) + quit("bad sblock magic number\n"); + dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1); + dev_bshift = ffs(dev_bsize) - 1; + if (dev_bsize != (1 << dev_bshift)) + quit("dev_bsize (%d) is not a power of 2", dev_bsize); + tp_bshift = ffs(TP_BSIZE) - 1; + if (TP_BSIZE != (1 << tp_bshift)) + quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE); +#ifdef FS_44INODEFMT + if (sblock->fs_inodefmt >= FS_44INODEFMT) + spcl.c_flags |= DR_NEWINODEFMT; +#endif + maxino = sblock->fs_ipg * sblock->fs_ncg; +#endif /* __linux__ */ + mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE); + usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); + dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char)); + dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char)); + metainomap = (char *)calloc((unsigned) mapsize, sizeof(char)); + if (usedinomap == NULL || dumpdirmap == NULL || + dumpinomap == NULL || metainomap == NULL) + quit("out of memory allocating inode maps\n"); + tapesize = 2 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); + + nonodump = spcl.c_level < honorlevel; + + if (!sizest) { + msg("Label: %s\n", spcl.c_label); + + msg("Writing %d Kilobyte records\n", ntrec); + + if (compressed) { + if (zipflag == COMPRESS_LZO) + msg("Compressing output (lzo)\n"); + else + msg("Compressing output at compression level %d (%s)\n", + compressed, zipflag == COMPRESS_ZLIB ? "zlib" : "bzlib"); + } + } + +#if defined(SIGINFO) + (void)signal(SIGINFO, statussig); +#endif + + if (!sizest) + msg("mapping (Pass I) [regular files]\n"); +#ifdef __linux__ + if (directory[0] == 0) + anydirskipped = mapfiles(maxino, &tapesize); + else { + if (LSTAT(pathname, &statbuf) == -1) { + msg("File cannot be accessed (%s).\n", pathname); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + filedev = statbuf.st_dev; + if (!(statbuf.st_mode & S_IFDIR)) /* is a file */ + anydirskipped = maponefile(maxino, &tapesize, + directory); + else + anydirskipped = mapfilesfromdir(maxino, &tapesize, + directory); + } + while (argc--) { + int anydirskipped2; + char *p = *argv; + /* check if file is available */ + if (LSTAT(p, &statbuf) == -1) { + msg("File cannot be accessed (%s).\n", p); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + /* check if file is on same unix partiton as the first + * argument */ + if (statbuf.st_dev != filedev) { + msg("Files are not on same file system (%s).\n", p); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + /* check if file is a directory */ + if (!(statbuf.st_mode & S_IFDIR)) + anydirskipped2 = maponefile(maxino, &tapesize, + p+strlen(dt->mnt_dir)); + else + /* read directory inodes. + * NOTE: nested directories are not recognized + * so inodes may be umped twice! + */ + anydirskipped2 = mapfilesfromdir(maxino, &tapesize, + p+strlen(dt->mnt_dir)); + if (!anydirskipped) + anydirskipped = anydirskipped2; + argv++; + } +#else + anydirskipped = mapfiles(maxino, &tapesize); +#endif + + if (!sizest) + msg("mapping (Pass II) [directories]\n"); + while (anydirskipped) { + anydirskipped = mapdirs(maxino, &tapesize); + } + + if (sizest) { + printf("%.0f\n", ((double)tapesize + 1 + ntrec) * TP_BSIZE); + exit(X_FINOK); + } /* stop here for size estimate */ + + if (pipeout || unlimited) { + tapesize += 1 + ntrec; /* 1 map header + trailer blocks */ + msg("estimated %ld blocks.\n", tapesize); + } else { + double fetapes; + + if (blocksperfiles) { + long tapesize_left; + + tapesize_left = tapesize; + fetapes = 0; + for (i = 1; i < *blocksperfiles && tapesize_left; i++) { + fetapes++; + if (tapesize_left > blocksperfiles[i]) + tapesize_left -= blocksperfiles[i]; + else + tapesize_left = 0; + } + if (tapesize_left) + fetapes += (double)tapesize_left / blocksperfiles[*blocksperfiles]; + } else if (cartridge) { + /* Estimate number of tapes, assuming streaming stops at + the end of each block written, and not in mid-block. + Assume no erroneous blocks; this can be compensated + for with an artificially low tape size. */ + fetapes = + ( (double) tapesize /* blocks */ + * TP_BSIZE /* bytes/block */ + * (1.0/density) /* 0.1" / byte " */ + + + (double) tapesize /* blocks */ + * (1.0/ntrec) /* streaming-stops per block */ + * 15.48 /* 0.1" / streaming-stop " */ + ) * (1.0 / tsize ); /* tape / 0.1" " */ + } else { + /* Estimate number of tapes, for old fashioned 9-track + tape */ + int tenthsperirg = (density == 625) ? 3 : 7; + fetapes = + ( (double) tapesize /* blocks */ + * TP_BSIZE /* bytes / block */ + * (1.0/density) /* 0.1" / byte " */ + + + (double) tapesize /* blocks */ + * (1.0/ntrec) /* IRG's / block */ + * tenthsperirg /* 0.1" / IRG " */ + ) * (1.0 / tsize ); /* tape / 0.1" " */ + } + etapes = fetapes; /* truncating assignment */ + etapes++; + /* count the dumped inodes map on each additional tape */ + tapesize += (etapes - 1) * + (howmany(mapsize * sizeof(char), TP_BSIZE) + 1); + tapesize += etapes + ntrec; /* headers + trailer blks */ + msg("estimated %ld blocks on %3.2f tape(s).\n", + tapesize, fetapes); + } + +#ifdef USE_QFA + if (tapepos) { + msg("writing QFA positions to %s\n", gTapeposfile); + if ((gTapeposfd = open(gTapeposfile, + O_WRONLY|O_CREAT|O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP + | S_IROTH | S_IWOTH)) < 0) + quit("can't open tapeposfile\n"); + /* print QFA-file header */ + snprintf(gTps, sizeof(gTps), "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); + gTps[sizeof(gTps) - 1] = '\0'; + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) + quit("can't write tapeposfile\n"); + sprintf(gTps, "ino\ttapeno\ttapepos\n"); + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) + quit("can't write tapeposfile\n"); + } +#endif /* USE_QFA */ + + /* + * Allocate tape buffer. + */ + if (!alloctape()) + quit( + "can't allocate tape buffers - try a smaller blocking factor.\n"); + + startnewtape(1); + tstart_writing = time(NULL); + dumpmap(usedinomap, TS_CLRI, maxino - 1); + + msg("dumping (Pass III) [directories]\n"); + dirty = 0; /* XXX just to get gcc to shut up */ + for (map = dumpdirmap, ino = 1; ino < maxino; ino++) { + if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ + dirty = *map++; + else + dirty >>= 1; + if ((dirty & 1) == 0) + continue; + /* + * Skip directory inodes deleted and maybe reallocated + */ + dp = getino(ino); + if ((dp->di_mode & IFMT) != IFDIR) + continue; +#ifdef __linux__ + /* + * Skip directory inodes deleted and not yes reallocated... + */ + if (dp->di_nlink == 0 || dp->di_dtime != 0) + continue; + if (vflag) + msg("dumping directory inode %lu\n", ino); + (void)dumpdirino(dp, ino); +#else + (void)dumpino(dp, ino); +#endif + } + + msg("dumping (Pass IV) [regular files]\n"); + for (map = dumpinomap, ino = 1; ino < maxino; ino++) { + if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ + dirty = *map++; + else + dirty >>= 1; + if ((dirty & 1) == 0) + continue; + /* + * Skip inodes deleted and reallocated as directories. + */ + dp = getino(ino); + if ((dp->di_mode & IFMT) == IFDIR) + continue; +#ifdef __linux__ + /* + * No need to check here for deleted and not yet reallocated + * inodes since this is done in dumpino(). + */ +#endif + if (vflag) { + if (mflag && TSTINO(ino, metainomap)) + msg("dumping regular inode %lu (meta only)\n", ino); + else + msg("dumping regular inode %lu\n", ino); + } + (void)dumpino(dp, ino, mflag && TSTINO(ino, metainomap)); + } + + tend_writing = time(NULL); + spcl.c_type = TS_END; + + if (Afile >= 0) { + volinfo[1] = ROOTINO; + memcpy(spcl.c_inos, volinfo, TP_NINOS * sizeof(dump_ino_t)); + spcl.c_flags |= DR_INODEINFO; + } + + /* + * Finish off the current tape record with trailer blocks, to ensure + * at least the data in the last partial record makes it to tape. + * Also make sure we write at least 1 trailer block. + */ + for (i = ntrec - (spcl.c_tapea % ntrec); i; --i) + writeheader(maxino - 1); + + tnow = trewind(); + + if (pipeout || fifoout) + msg("%ld blocks (%.2fMB)\n", spcl.c_tapea, + ((double)spcl.c_tapea * TP_BSIZE / 1048576)); + else + msg("%ld blocks (%.2fMB) on %d volume(s)\n", + spcl.c_tapea, + ((double)spcl.c_tapea * TP_BSIZE / 1048576), + spcl.c_volume); + + /* report dump performance, avoid division by zero */ + if (tend_writing - tstart_writing == 0) + msg("finished in less than a second\n"); + else + msg("finished in %d seconds, throughput %d kBytes/sec\n", + tend_writing - tstart_writing, + spcl.c_tapea / (tend_writing - tstart_writing)); + + putdumptime(); + msg("Date of this level %s dump: %s", level, + spcl.c_date == 0 ? "the epoch\n" : ctime4(&spcl.c_date)); + msg("Date this dump completed: %s", ctime(&tnow)); + + msg("Average transfer rate: %ld kB/s\n", xferrate / tapeno); + if (compressed) { + long tapekb = bytes_written / 1024; + double rate = .0005 + (double) spcl.c_tapea / tapekb; + msg("Wrote %ldkB uncompressed, %ldkB compressed, %1.3f:1\n", + spcl.c_tapea, tapekb, rate); + } + + if (Afile >= 0) + msg("Archiving dump to %s\n", Apath); + + broadcast("DUMP IS DONE!\7\7\n"); + msg("DUMP IS DONE\n"); + Exit(X_FINOK); + /* NOTREACHED */ + return 0; /* gcc - shut up */ +} + +static void +usage(void) +{ + char white[MAXPATHLEN]; + const char *ext2ver, *ext2date; + + memset(white, ' ', MAXPATHLEN); + white[MIN(strlen(__progname), MAXPATHLEN - 1)] = '\0'; + +#ifdef __linux__ + ext2fs_get_library_version(&ext2ver, &ext2date); + fprintf(stderr, "%s %s (using libext2fs %s of %s)\n", + __progname, _DUMP_VERSION, ext2ver, ext2date); +#else + fprintf(stderr, "%s %s\n", __progname, _DUMP_VERSION); +#endif + fprintf(stderr, + "usage:\t%s [-level#] [-ac" +#ifdef KERBEROS + "k" +#endif + "mMnqSuv" + "] [-A file] [-B records] [-b blocksize]\n" + "\t%s [-d density] [-D file] [-e inode#,inode#,...] [-E file]\n" + "\t%s [-f file] [-h level] [-I nr errors] " +#ifdef HAVE_BZLIB + "[-j zlevel] " +#endif +#ifdef USE_QFA + "[-Q file]\n" +#endif + "\t%s [-s feet] " + "[-T date] " +#ifdef HAVE_LZO + "[-y] " +#endif +#ifdef HAVE_ZLIB + "[-z zlevel] " +#endif + "filesystem\n" + "\t%s [-W | -w]\n", + __progname, white, white, white, __progname); + exit(X_STARTUP); +} + +/* + * Pick up a numeric argument. It must be nonnegative and in the given + * range (except that a vmax of 0 means unlimited). + */ +static long +numarg(const char *meaning, long vmin, long vmax) +{ + char *p; + long val; + + val = strtol(optarg, &p, 10); + if (*p) + errx(X_STARTUP, "illegal %s -- %s", meaning, optarg); + if (val < vmin || (vmax && val > vmax)) + errx(X_STARTUP, "%s must be between %ld and %ld", meaning, vmin, vmax); + return (val); +} + +/* + * The same as numarg, just that it expects a comma separated list of numbers + * and returns an array of longs with the first element containing the number + * values in that array. + */ +static long * +numlistarg(const char *meaning, long vmin, long vmax) +{ + char *p; + long *vals,*curval; + long valnum; + + p = optarg; + vals = NULL; + valnum = 0; + do { + valnum++; + if ( !(vals = realloc(vals, (valnum + 1) * sizeof(*vals))) ) + errx(X_STARTUP, "allocating memory failed"); + curval = vals + valnum; + *curval = strtol(p, &p, 10); + if (*p && *p!=',') + errx(X_STARTUP, "illegal %s -- %s", meaning, optarg); + if (*curval < vmin || (vmax && *curval > vmax)) + errx(X_STARTUP, "%s must be between %ld and %ld", meaning, vmin, vmax); + *vals = valnum; + if (*p) p++; + } while(*p); + return (vals); +} + +void +sig(int signo) +{ + switch(signo) { + case SIGALRM: + case SIGBUS: + case SIGFPE: + case SIGHUP: + case SIGTERM: + case SIGTRAP: + if (pipeout || fifoout) + quit("Signal on pipe: cannot recover\n"); + msg("Rewriting attempted as response to unknown signal: %d.\n", signo); + (void)fflush(stderr); + (void)fflush(stdout); + close_rewind(); + exit(X_REWRITE); + /* NOTREACHED */ + case SIGSEGV: + msg("SIGSEGV: ABORTING!\n"); + (void)signal(SIGSEGV, SIG_DFL); + (void)kill(0, SIGSEGV); + /* NOTREACHED */ + } +} + +const char * +rawname(const char *cp) +{ +#ifdef __linux__ + return cp; +#else /* __linux__ */ + static char rawbuf[MAXPATHLEN]; + char *dp = strrchr(cp, '/'); + + if (dp == NULL) + return (NULL); + (void)strncpy(rawbuf, cp, min(dp-cp, MAXPATHLEN - 1)); + rawbuf[min(dp-cp, MAXPATHLEN-1)] = '\0'; + (void)strncat(rawbuf, "/r", MAXPATHLEN - 1 - strlen(rawbuf)); + (void)strncat(rawbuf, dp + 1, MAXPATHLEN - 1 - strlen(rawbuf)); + return (rawbuf); +#endif /* __linux__ */ +} + +/* + * obsolete -- + * Change set of key letters and ordered arguments into something + * getopt(3) will like. + */ +static void +obsolete(int *argcp, char **argvp[]) +{ + int argc, flags; + char *ap, **argv, *flagsp=NULL, **nargv, *p=NULL; + + /* Setup. */ + argv = *argvp; + argc = *argcp; + + /* Return if no arguments or first argument has leading dash. */ + ap = argv[1]; + if (argc == 1 || *ap == '-') + return; + + /* Allocate space for new arguments. */ + if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || + (p = flagsp = malloc(strlen(ap) + 2)) == NULL) + err(X_STARTUP, "malloc new args"); + + *nargv++ = *argv; + argv += 2; + + for (flags = 0; *ap; ++ap) { + switch (*ap) { + case 'A': + case 'B': + case 'b': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + case 'h': + case 'L': + case 'Q': + case 's': + case 'T': + if (*argv == NULL) { + warnx("option requires an argument -- %c", *ap); + usage(); + } + if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) + err(X_STARTUP, "malloc arg"); + nargv[0][0] = '-'; + nargv[0][1] = *ap; + (void)strcpy(&nargv[0][2], *argv); + ++argv; + ++nargv; + break; + default: + if (!flags) { + *p++ = '-'; + flags = 1; + } + *p++ = *ap; + break; + } + } + + /* Terminate flags. */ + if (flags) { + *p = '\0'; + *nargv++ = flagsp; + } + + /* Copy remaining arguments. */ + while ((*nargv++ = *argv++)); + + /* Update argument count. */ + *argcp = nargv - *argvp - 1; +} + +/* + * This tests whether an inode is in the exclude bitmap + */ +int +exclude_ino(dump_ino_t ino) +{ + /* if the inode exclude bitmap exists and covers given inode */ + if (iexclude_bitmap && iexclude_bitmap_bytes > ino / 8) { + /* then check this inode against it */ + int idx = iexclude_bitmap[ino / 8]; + if (idx & (1 << (ino % 8))) + return 1; + } + return 0; +} + +/* + * This adds an inode to the exclusion bitmap if it isn't already there + */ +void +do_exclude_ino(dump_ino_t ino, const char *reason) +{ + if (exclude_ino(ino)) + return; + + if (vflag) { + if (reason) + msg("Excluding inode %u (%s) from dump\n", ino, reason); + else + msg("Excluding inode %u from dump\n", ino); + } + + /* check for enough mem; initialize */ + if ((ino/8 + 1) > iexclude_bitmap_bytes) { + if (iexclude_bitmap_bytes == 0) { + unsigned int j; + iexclude_bitmap_bytes = 2 * (ino/8 + 1); + iexclude_bitmap = (char*) malloc(iexclude_bitmap_bytes); + if (iexclude_bitmap == NULL) { + msg("allocating memory failed\n"); + exit(X_STARTUP); + } + for (j = 0; j < iexclude_bitmap_bytes; j++) + iexclude_bitmap[j] = 0; + } + else { + unsigned int oldsize = iexclude_bitmap_bytes; + iexclude_bitmap_bytes *= + (ino / 8 + 1) / iexclude_bitmap_bytes + 1; + iexclude_bitmap = (char*) realloc(iexclude_bitmap, + iexclude_bitmap_bytes); + if (iexclude_bitmap == NULL) { + msg("allocating memory failed\n"); + exit(X_STARTUP); + } + for( ; oldsize < iexclude_bitmap_bytes; oldsize++) + iexclude_bitmap[oldsize] = 0; + } + } + + iexclude_bitmap[ino / 8] |= 1 << (ino % 8); +} + +static void +do_exclude_ino_str(char * ino) { + char *r; + unsigned long inod; + + inod = strtoul(ino, &r, 10); + if (( *r != '\0' && !isspace(*r) ) || inod <= ROOTINO) { + msg("Invalid inode argument %s\n", ino); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + do_exclude_ino(inod, NULL); +} + +/* + * This reads a file containing one inode number per line and exclude them all + */ +static void +do_exclude_from_file(char *file) { + FILE *f; + char *p, fname[MAXPATHLEN]; + + + if (!( f = fopen(file, "r")) ) { + msg("Cannot open file for reading: %s\n", file); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } + while (( p = fgets(fname, MAXPATHLEN, f))) { + if ( *p && *(p + strlen(p) - 1) == '\n' ) /* possible null string */ + *(p + strlen(p) - 1) = '\0'; + if ( !*p ) /* skip empty lines */ + continue; + do_exclude_ino_str(p); + } + fclose(f); +} + +static void incompat_flags(int cond, char flag1, char flag2) { + if (cond) { + msg("You cannot use the %c and %c flags together.\n", + flag1, flag2); + msg("The ENTIRE dump is aborted.\n"); + exit(X_STARTUP); + } +} diff --git a/dump/optr.c b/dump/optr.c new file mode 100644 index 0000000..a4504da --- /dev/null +++ b/dump/optr.c @@ -0,0 +1,736 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: optr.c,v 1.39 2004/07/05 15:12:45 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#endif + +#include "dump.h" +#include "pathnames.h" +#include "bylabel.h" + +static void alarmcatch __P((int)); +int datesort __P((const void *, const void *)); +static void sendmes __P((const char *, const char *)); + +/* List of filesystem types that we can dump (same ext2 on-disk format) */ +static char *fstypes[] = { "ext2", "ext3", "InterMezzo", NULL }; + +/* + * Query the operator; This previously-fascist piece of code + * no longer requires an exact response. + * It is intended to protect dump aborting by inquisitive + * people banging on the console terminal to see what is + * happening which might cause dump to croak, destroying + * a large number of hours of work. + * + * Every 2 minutes we reprint the message, alerting others + * that dump needs attention. + */ +static int timeout; +static const char *attnmessage; /* attention message */ + +int +query(const char *question) +{ + char replybuffer[64]; + int back, errcount; + FILE *mytty; + time_t firstprompt, when_answered; + + if (qflag) { + msg("%s - forced abort\n", question); + dumpabort(0); + /* NOTREACHED */ + } + + firstprompt = time(NULL); + + if ((mytty = fopen(_PATH_TTY, "r")) == NULL) + quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno)); + attnmessage = question; + timeout = 0; + alarmcatch(0); + back = -1; + errcount = 0; + do { + if (fgets(replybuffer, 63, mytty) == NULL) { + clearerr(mytty); + if (++errcount > 30) /* XXX ugly */ + quit("excessive operator query failures\n"); + } else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') { + back = 1; + } else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') { + back = 0; + } else { + (void) fprintf(stderr, + " DUMP: \"Yes\" or \"No\"?\n"); + (void) fprintf(stderr, + " DUMP: %s: (\"yes\" or \"no\") ", question); + } + } while (back < 0); + + /* + * Turn off the alarm, and reset the signal to trap out.. + */ + (void) alarm(0); + if (signal(SIGALRM, sig) == SIG_IGN) + signal(SIGALRM, SIG_IGN); + (void) fclose(mytty); + when_answered = time(NULL); + /* + * Adjust the base for time estimates to ignore time we spent waiting + * for operator input. + */ + if (tstart_writing != 0) + tstart_writing += (when_answered - firstprompt); + return(back); +} + +char lastmsg[BUFSIZ]; + +/* + * Alert the console operator, and enable the alarm clock to + * sleep for 2 minutes in case nobody comes to satisfy dump + */ +static void +alarmcatch(UNUSED(int signo)) +{ + int save_errno = errno; + if (notify == 0) { + if (timeout == 0) + (void) fprintf(stderr, + " DUMP: %s: (\"yes\" or \"no\") ", + attnmessage); + else + msgtail("\7\7"); + } else { + if (timeout) { + msgtail("\n"); + broadcast(""); /* just print last msg */ + } + (void) fprintf(stderr," DUMP: %s: (\"yes\" or \"no\") ", + attnmessage); + } + signal(SIGALRM, alarmcatch); + (void) alarm(120); + timeout = 1; + errno = save_errno; +} + +/* + * Here if an inquisitive operator interrupts the dump program + */ +void +interrupt(UNUSED(int signo)) +{ + msg("Interrupt received.\n"); + if (query("Do you want to abort dump?")) + dumpabort(0); +} + +/* + * The following variables and routines manage alerting + * operators to the status of dump. + * This works much like wall(1) does. + */ +struct group *gp; + +/* + * Get the names from the group entry "operator" to notify. + */ +void +set_operators(void) +{ + if (!notify) /*not going to notify*/ + return; + gp = getgrnam(OPGRENT); + (void) endgrent(); + if (gp == NULL) { + msg("No group entry for %s.\n", OPGRENT); + notify = 0; + return; + } +} + +struct tm *localclock; + +/* + * We fork a child to do the actual broadcasting, so + * that the process control groups are not messed up + */ +void +broadcast(const char *message) +{ + time_t clock; + FILE *f_utmp; + struct utmp utmp; + char **np; + int pid, s; + + if (!notify || gp == NULL) + return; + + switch (pid = fork()) { + case -1: + return; + case 0: + break; + default: + while (wait(&s) != pid) + continue; + return; + } + + clock = time(NULL); + localclock = localtime(&clock); + + if ((f_utmp = fopen(_PATH_UTMP, "r")) == NULL) { + msg("Cannot open %s: %s\n", _PATH_UTMP, strerror(errno)); + return; + } + + while (!feof(f_utmp)) { + if (fread((char *) &utmp, sizeof (struct utmp), 1, f_utmp) != 1) + break; + if (utmp.ut_name[0] == 0) + continue; + for (np = gp->gr_mem; *np; np++) { + if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0) + continue; + /* + * Do not send messages to operators on dialups + */ + if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0) + continue; +#ifdef DEBUG + msg("Message to %s at %s\n", *np, utmp.ut_line); +#endif + sendmes(utmp.ut_line, message); + } + } + (void) fclose(f_utmp); + Exit(0); /* the wait in this same routine will catch this */ + /* NOTREACHED */ +} + +static void +sendmes(const char *tty, const char *message) +{ + char t[MAXPATHLEN], buf[BUFSIZ]; + const char *cp; + int lmsg = 1; + FILE *f_tty; + + (void) strcpy(t, _PATH_DEV); + (void) strncat(t, tty, sizeof t - strlen(_PATH_DEV) - 1); + + if ((f_tty = fopen(t, "w")) != NULL) { + setbuf(f_tty, buf); + (void) fprintf(f_tty, + "\n\ +\7\7\7Message from the dump program to all operators at %d:%02d ...\r\n\n\ +DUMP: NEEDS ATTENTION: ", + localclock->tm_hour, localclock->tm_min); + for (cp = lastmsg; ; cp++) { + if (*cp == '\0') { + if (lmsg) { + cp = message; + if (!(cp && *cp != '\0')) + break; + lmsg = 0; + } else + break; + } + if (*cp == '\n') + (void) putc('\r', f_tty); + (void) putc(*cp, f_tty); + } + (void) fclose(f_tty); + } +} + +/* + * print out an estimate of the amount of time left to do the dump + */ + +time_t tschedule = 0; + +void +timeest(void) +{ + time_t tnow = time(NULL); + + if (tnow >= tschedule) { + char *buf = mktimeest(tnow); + tschedule = tnow + 300; + if (buf) { + fprintf(stderr, " DUMP: "); + fwrite(buf, strlen(buf), 1, stderr); + fflush(stderr); + } + } +} + +void +#ifdef __STDC__ +msg(const char *fmt, ...) +#else +msg(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void) fprintf(stderr," DUMP: "); +#ifdef TDEBUG + (void) fprintf(stderr, "pid=%d ", getpid()); +#endif +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + (void) fflush(stdout); + (void) fflush(stderr); +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) vsnprintf(lastmsg, sizeof(lastmsg), fmt, ap); + va_end(ap); +} + +void +#ifdef __STDC__ +msgtail(const char *fmt, ...) +#else +msgtail(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) vfprintf(stderr, fmt, ap); + va_end(ap); +} + +void +#ifdef __STDC__ +quit(const char *fmt, ...) +#else +quit(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void) fprintf(stderr," DUMP: "); +#ifdef TDEBUG + (void) fprintf(stderr, "pid=%d ", getpid()); +#endif +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + (void) fflush(stdout); + (void) fflush(stderr); + dumpabort(0); +} + +/* + * Tell the operator what has to be done; + * we don't actually do it + */ + +struct pfstab { + struct pfstab *pf_next; + struct dumpdates *pf_dd; + struct mntent *pf_mntent; +}; + +static struct pfstab *table; + +static struct mntent * +allocfsent(struct mntent *fs) +{ + struct mntent *new; + const char *disk; + struct stat buf, tabbuf; + struct pfstab *tabpf; + struct mntent *tabfs; + + new = (struct mntent *)malloc(sizeof (*fs)); + if (new == NULL) + quit("%s\n", strerror(errno)); + + /* Translade UUID=, LABEL= ... */ + disk = get_device_name(fs->mnt_fsname); + if (disk == NULL) + disk = strdup(fs->mnt_fsname); + + /* Discard non block devices */ + if (stat(disk, &buf) != 0 || !S_ISBLK(buf.st_mode)) { + free(new); + return NULL; + } + + /* Discard same major/minor devices */ + for (tabpf = table; tabpf != NULL; tabpf = tabpf->pf_next) { + tabfs = tabpf->pf_mntent; + if (stat(tabfs->mnt_fsname, &tabbuf) != 0) + /* should not happen */ + quit("Cannot access %s\n", tabfs->mnt_fsname); + if (tabbuf.st_rdev == buf.st_rdev) { + free(new); + /* Copy passno and freq from /etc/fstab because + * /etc/mtab does always have them as 0 0 */ + if (!tabfs->mnt_passno) + tabfs->mnt_passno = fs->mnt_passno; + if (!tabfs->mnt_freq) + tabfs->mnt_freq = fs->mnt_freq; + return NULL; + } + } + + if (strlen(fs->mnt_dir) > 1 && fs->mnt_dir[strlen(fs->mnt_dir) - 1] == '/') + fs->mnt_dir[strlen(fs->mnt_dir) - 1] = '\0'; + if ((new->mnt_dir = strdup(fs->mnt_dir)) == NULL || + (new->mnt_type = strdup(fs->mnt_type)) == NULL || + (new->mnt_opts = strdup(fs->mnt_opts)) == NULL || + (new->mnt_fsname = strdup(disk)) == NULL) + quit("%s\n", strerror(errno)); + new->mnt_passno = fs->mnt_passno; + new->mnt_freq = fs->mnt_freq; + return (new); +} + +void +getfstab(void) +{ + struct mntent *fs; + struct pfstab *pf; + struct pfstab *pfold = NULL; + FILE *mntfp; + char *mnttables[] = { _PATH_MOUNTED, _PATH_MNTTAB, 0 }; + int i; + + for (i = 0; mnttables[i]; i++) { + mntfp = setmntent(mnttables[i], "r"); + if (mntfp == NULL) { + msg("Can't open %s for dump table information: %s\n", + mnttables[i], strerror(errno)); + continue; + } + while ((fs = getmntent(mntfp)) != NULL) { + fs = allocfsent(fs); + if (!fs) + continue; + fs->mnt_passno = 0; + if ((pf = (struct pfstab *)malloc(sizeof (*pf))) == NULL) + quit("%s\n", strerror(errno)); + pf->pf_mntent = fs; + pf->pf_next = NULL; + + /* keep table in /etc/fstab order for use with -w and -W */ + if (pfold) { + pfold->pf_next = pf; + pfold = pf; + } else + pfold = table = pf; + } + (void) endmntent(mntfp); + } +} + +/* + * Search in the fstab for a file name. + * This file name can be either the special or the path file name. + * + * The entries in the fstab are the BLOCK special names, not the + * character special names. + * The caller of fstabsearch assures that the character device + * is dumped (that is much faster) + * + * The file name can omit the leading '/'. + */ +struct mntent * +fstabsearch(const char *key) +{ + struct pfstab *pf; + struct mntent *fs; + const char *rn; + + for (pf = table; pf != NULL; pf = pf->pf_next) { + fs = pf->pf_mntent; + if (strcmp(fs->mnt_dir, key) == 0 || + strcmp(fs->mnt_fsname, key) == 0) + return (fs); + rn = rawname(fs->mnt_fsname); + if (rn != NULL && strcmp(rn, key) == 0) + return (fs); + if (key[0] != '/') { + if (*fs->mnt_fsname == '/' && + strcmp(fs->mnt_fsname + 1, key) == 0) + return (fs); + if (*fs->mnt_dir == '/' && + strcmp(fs->mnt_dir + 1, key) == 0) + return (fs); + } + } + return (NULL); +} + +#ifdef __linux__ +struct mntent * +fstabsearchdir(const char *key, char *directory) +{ + struct pfstab *pf; + struct mntent *fs; + struct mntent *found_fs = NULL; + unsigned int size = 0; + struct stat buf; + + if (stat(key, &buf) == 0 && S_ISBLK(buf.st_mode)) + return NULL; + + for (pf = table; pf != NULL; pf = pf->pf_next) { + fs = pf->pf_mntent; + if (strlen(fs->mnt_dir) > size && + strlen(key) > strlen(fs->mnt_dir) && + strncmp(fs->mnt_dir, key, strlen(fs->mnt_dir)) == 0 && + (key[strlen(fs->mnt_dir)] == '/' || + fs->mnt_dir[strlen(fs->mnt_dir) - 1] == '/')) { + found_fs = fs; + size = strlen(fs->mnt_dir); + } + } + if (found_fs != NULL) { + /* + * Ok, we have found a fstab entry which matches the argument + * We have to split the argument name into: + * - a device name (from the fstab entry) + * - a directory name on this device + */ + strcpy(directory, key + size); + } + return(found_fs); +} +#endif + +static void +print_wmsg(char arg, int dumpme, const char *dev, int level, + const char *mtpt, time_t ddate) +{ +#ifdef FDEBUG + printf("checking dev %s: lvl %d, mtpt %s\n", dev, level, mtpt); +#endif + if (!dumpme && arg == 'w') + return; + + (void) printf("%c %8s\t(%6s) Last dump: ", + dumpme && (arg != 'w') ? '>' : ' ', + dev, + mtpt ? mtpt : ""); + + /* + * Check ddate > 365 to avoid issues with fs in stab but not dumpdates. + * Not a problem, because ddate is in seconds since the epoch anyways. + */ + if (ddate > 365) { + char *date, *d; + + date = (char *)ctime(&ddate); + d = strchr(date, '\n'); + if (d) *d = '\0'; + printf("Level %d, Date %s\n", level, date); + } else + printf("never\n"); +} + +/* + * Tell the operator what to do + */ +void +lastdump(char arg) /* w ==> just what to do; W ==> most recent dumps */ +{ + struct pfstab *pf; + time_t tnow; + + tnow = time(NULL); + getfstab(); /* /etc/fstab input */ + initdumptimes(0); /* dumpdates input */ + if (ddatev == NULL && table == NULL) { + (void) printf("No %s or %s file found\n", + _PATH_MNTTAB, dumpdates); + return; + } + + if (arg == 'w') + (void) printf("Dump these file systems:\n"); + else + (void) printf("Last dump(s) done (Dump '>' file systems):\n"); + + /* For files in dumpdates, get the last dump level and date */ + if (ddatev != NULL) { + struct dumpdates *dtwalk = NULL; + int i; + char *lastname; + + qsort((char *) ddatev, nddates, sizeof(struct dumpdates *), datesort); + + lastname = "??"; + ITITERATE(i, dtwalk) { + struct mntent *dt; + if (strncmp(lastname, dtwalk->dd_name, + sizeof(dtwalk->dd_name)) == 0) + continue; + lastname = dtwalk->dd_name; + if ((dt = dtwalk->dd_fstab) != NULL) { + /* Overload fs_freq as dump level and + * fs_passno as date, because we can't + * change struct fstab format. + * A positive fs_freq means this + * filesystem needs to be dumped. + */ + dt->mnt_passno = dtwalk->dd_ddate; + if (dt->mnt_freq > 0 && (dtwalk->dd_ddate < + tnow - (dt->mnt_freq * 86400))) + dt->mnt_freq = dtwalk->dd_level; + else + dt->mnt_freq = -dtwalk->dd_level; +#ifdef FDEBUG + printf("%s fs_freq set to %d\n", lastname, + dt->mnt_freq); +#endif + } + } + } + + /* print in /etc/fstab order only those filesystem types we can dump */ + for (pf = table; pf != NULL; pf = pf->pf_next) { + struct mntent *dt = pf->pf_mntent; + char **type; + + for (type = fstypes; *type != NULL; type++) { + if (strncmp(dt->mnt_type, *type, + sizeof(dt->mnt_type)) == 0) { + const char *disk = get_device_name(dt->mnt_fsname); + print_wmsg(arg, dt->mnt_freq > 0, + disk ? disk : dt->mnt_fsname, + dt->mnt_freq < 0 ? -dt->mnt_freq : + dt->mnt_freq, + dt->mnt_dir, + dt->mnt_passno); + } + } + } + + /* print in /etc/dumpdates order if not in /etc/fstab */ + if (ddatev != NULL) { + struct dumpdates *dtwalk = NULL; + char *lastname; + int i; + + lastname = "??"; + ITITERATE(i, dtwalk) { + if (strncmp(lastname, dtwalk->dd_name, + sizeof(dtwalk->dd_name)) == 0 || + dtwalk->dd_fstab != NULL) + continue; + lastname = dtwalk->dd_name; + print_wmsg(arg, 0, dtwalk->dd_name, + dtwalk->dd_level, NULL, dtwalk->dd_ddate); + } + } +} + +int +datesort(const void *a1, const void *a2) +{ + struct dumpdates *d1 = *(struct dumpdates **)a1; + struct dumpdates *d2 = *(struct dumpdates **)a2; + int diff; + + diff = strncmp(d1->dd_name, d2->dd_name, sizeof(d1->dd_name)); + if (diff == 0) + return (d2->dd_ddate - d1->dd_ddate); + return (diff); +} diff --git a/dump/tape.c b/dump/tape.c new file mode 100644 index 0000000..2df4d1e --- /dev/null +++ b/dump/tape.c @@ -0,0 +1,1495 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: tape.c,v 1.86 2004/07/07 11:07:29 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#include +#else +int write(), read(); +#endif + +#ifdef __linux__ +#include +#include +#include +#include /* for definition of BLKFLSBUF */ +#ifndef BLKFLSBUF /* last resort... */ +#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */ +#endif +#include +#endif +#include +#include +#include +#include +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#elif defined sunos +#include + +#include +#include +#else +#include +#include +#endif /* __linux__ */ + +#include + +#ifdef HAVE_ZLIB +#include +#endif /* HAVE_ZLIB */ + +#ifdef HAVE_BZLIB +#include +#endif /* HAVE_BZLIB */ + +#ifdef HAVE_LZO +#include +#endif /* HAVE_LZO */ + +#include "dump.h" + +int writesize; /* size of malloc()ed buffer for tape */ +long lastspclrec = -1; /* tape block number of last written header */ +int trecno = 0; /* next record to write in current block */ +extern long *blocksperfiles; /* number of blocks per output file(s) */ +long blocksperfiles_current; /* current position in blocksperfiles */ +long blocksthisvol; /* number of blocks on current output file */ +extern int ntrec; /* blocking factor on tape */ +extern int cartridge; +char *nexttape; +extern pid_t rshpid; +int eot_code = 1; +long long tapea_bytes = 0; /* bytes_written at start of current volume */ +static int magtapeout; /* output is really a tape */ + +static ssize_t dump_atomic_read __P((int, char *, size_t)); +static ssize_t dump_atomic_write __P((int, const char *, size_t)); +#ifdef WRITEDEBUG +static void doslave __P((int, int, int)); +#else +static void doslave __P((int, int)); +#endif +static void enslave __P((void)); +static void flushtape __P((void)); +static void killall __P((void)); +static void rollforward __P((void)); +#ifdef USE_QFA +static int GetTapePos __P((long long *)); +static int MkTapeString __P((struct s_spcl *, long long)); +#define FILESQFAPOS 20 +#endif + +/* + * Concurrent dump mods (Caltech) - disk block reading and tape writing + * are exported to several slave processes. While one slave writes the + * tape, the others read disk blocks; they pass control of the tape in + * a ring via signals. The parent process traverses the filesystem and + * sends writeheader()'s and lists of daddr's to the slaves via pipes. + * The following structure defines the instruction packets sent to slaves. + */ +struct req { + ext2_loff_t dblk; + int count; +}; +int reqsiz; + +struct slave_results { + ssize_t unclen; /* uncompressed length */ + ssize_t clen; /* compressed length */ +}; + +#define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */ +struct slave { + int tapea; /* header number at start of this chunk */ + int count; /* count to next header (used for TS_TAPE */ + /* after EOT) */ + int inode; /* inode that we are currently dealing with */ + int fd; /* FD for this slave */ + int pid; /* PID for this slave */ + int sent; /* 1 == we've sent this slave requests */ + int firstrec; /* record number of this block */ + char (*tblock)[TP_BSIZE]; /* buffer for data blocks */ + struct req *req; /* buffer for requests */ +} slaves[SLAVES+1]; +struct slave *slp; + +char (*nextblock)[TP_BSIZE]; + +static time_t tstart_volume; /* time of volume start */ +static int tapea_volume; /* value of spcl.c_tapea at volume start */ + +int master; /* pid of master, for sending error signals */ +int tenths; /* length of tape overhead per block written */ +static int caught; /* have we caught the signal to proceed? */ +static int ready; /* have we reached the lock point without having */ + /* received the SIGUSR2 signal from the prev slave? */ +static sigjmp_buf jmpbuf; /* where to jump to if we are ready when the */ + /* SIGUSR2 arrives from the previous slave */ +#ifdef USE_QFA +static int gtperr = 0; +#endif + +int +alloctape(void) +{ + int pgoff = getpagesize() - 1; + char *buf; + int i; + + writesize = ntrec * TP_BSIZE; + reqsiz = (ntrec + 1) * sizeof(struct req); + /* + * CDC 92181's and 92185's make 0.8" gaps in 1600-bpi start/stop mode + * (see DEC TU80 User's Guide). The shorter gaps of 6250-bpi require + * repositioning after stopping, i.e, streaming mode, where the gap is + * variable, 0.30" to 0.45". The gap is maximal when the tape stops. + */ + if (!blocksperfiles && !unlimited) + tenths = (cartridge ? 16 : density == 625 ? 5 : 8); + else { + tenths = 0; + density = 1; + } + /* + * Allocate tape buffer contiguous with the array of instruction + * packets, so flushtape() can write them together with one write(). + * Align tape buffer on page boundary to speed up tape write(). + */ + for (i = 0; i <= SLAVES; i++) { + buf = (char *) + malloc((unsigned)(reqsiz + writesize + pgoff + TP_BSIZE)); + if (buf == NULL) + return(0); + slaves[i].tblock = (char (*)[TP_BSIZE]) +#ifdef __linux__ + (((long)&buf[reqsiz] + pgoff) &~ pgoff); +#else + (((long)&buf[ntrec + 1] + pgoff) &~ pgoff); +#endif + slaves[i].req = (struct req *)slaves[i].tblock - ntrec - 1; + } + slp = &slaves[0]; + slp->count = 1; + slp->tapea = 0; + slp->firstrec = 0; + nextblock = slp->tblock; + return(1); +} + +void +writerec(const void *dp, int isspcl) +{ + + slp->req[trecno].dblk = (ext2_loff_t)0; + slp->req[trecno].count = 1; + /* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */ + *(union u_spcl *)(*(nextblock)) = *(union u_spcl *)dp; + + /* Need to write it to the archive file */ + if (! AfileActive && isspcl && (spcl.c_type == TS_END)) + AfileActive = 1; + if (AfileActive && Afile >= 0) { + /* When we dump an inode which is not a directory, + * it means we ended the archive contents */ + if (isspcl && (spcl.c_type == TS_INODE) && + ((spcl.c_dinode.di_mode & S_IFMT) != IFDIR)) + AfileActive = 0; + else { + union u_spcl tmp; + tmp = *(union u_spcl *)dp; + /* Write the record, _uncompressed_ */ + if (isspcl) { + tmp.s_spcl.c_flags &= ~DR_COMPRESSED; + mkchecksum(&tmp); + } + if (write(Afile, &tmp, TP_BSIZE) != TP_BSIZE) + msg("error writing archive file: %s\n", + strerror(errno)); + } + } + + nextblock++; + if (isspcl) + lastspclrec = spcl.c_tapea; + trecno++; + spcl.c_tapea++; + if (trecno >= ntrec) + flushtape(); +} + +void +dumpblock(blk_t blkno, int size) +{ + int avail, tpblks; + ext2_loff_t dblkno; + + dblkno = fsbtodb(sblock, blkno); + tpblks = size >> tp_bshift; + while ((avail = MIN(tpblks, ntrec - trecno)) > 0) { + slp->req[trecno].dblk = dblkno; + slp->req[trecno].count = avail; + trecno += avail; + spcl.c_tapea += avail; + if (trecno >= ntrec) + flushtape(); + dblkno += avail << (tp_bshift - dev_bshift); + tpblks -= avail; + } +} + +int nogripe = 0; + +static void +tperror(int errnum) +{ + + if (pipeout) { + msg("write error on %s: %s\n", tape, strerror(errnum)); + quit("Cannot recover\n"); + /* NOTREACHED */ + } + msg("write error %d blocks into volume %d: %s\n", + blocksthisvol, tapeno, strerror(errnum)); + broadcast("DUMP WRITE ERROR!\n"); + if (query("Do you want to rewrite this volume?")) { + msg("Closing this volume. Prepare to restart with new media;\n"); + msg("this dump volume will be rewritten.\n"); + killall(); + nogripe = 1; + close_rewind(); + Exit(X_REWRITE); + } + if (query("Do you want to start the next tape?")) + return; + dumpabort(0); +} + +static void +sigpipe(UNUSED(int signo)) +{ + + quit("Broken pipe\n"); +} + +/* + * do_stats -- + * Update xferrate stats + */ +time_t +do_stats(void) +{ + time_t tnow, ttaken; + int blocks; + + tnow = time(NULL); + ttaken = tnow - tstart_volume; + blocks = spcl.c_tapea - tapea_volume; + msg("Volume %d completed at: %s", tapeno, ctime(&tnow)); + if (! compressed) + msg("Volume %d %ld blocks (%.2fMB)\n", tapeno, + blocks, ((double)blocks * TP_BSIZE / 1048576)); + if (ttaken > 0) { + long volkb = (bytes_written - tapea_bytes) / 1024; + long txfrate = volkb / ttaken; + msg("Volume %d took %d:%02d:%02d\n", tapeno, + ttaken / 3600, (ttaken % 3600) / 60, ttaken % 60); + msg("Volume %d transfer rate: %ld kB/s\n", tapeno, + txfrate); + xferrate += txfrate; + if (compressed) { + double rate = .0005 + (double) blocks / (double) volkb; + msg("Volume %d %ldkB uncompressed, %ldkB compressed," + " %1.3f:1\n", + tapeno, blocks, volkb, rate); + } + } + return(tnow); +} + +char * +mktimeest(time_t tnow) +{ + static char msgbuf[128]; + time_t deltat; + + msgbuf[0] = '\0'; + + if (blockswritten < 500) + return NULL; + if (blockswritten > tapesize) + tapesize = blockswritten; + deltat = tstart_writing - tnow + (1.0 * (tnow - tstart_writing)) + / blockswritten * tapesize; + if (tnow > tstart_volume) + (void)snprintf(msgbuf, sizeof(msgbuf), + "%3.2f%% done at %ld kB/s, finished in %d:%02d\n", + (blockswritten * 100.0) / tapesize, + (spcl.c_tapea - tapea_volume) / (tnow - tstart_volume), + (int)(deltat / 3600), (int)((deltat % 3600) / 60)); + else + (void)snprintf(msgbuf, sizeof(msgbuf), + "%3.2f%% done, finished in %d:%02d\n", + (blockswritten * 100.0) / tapesize, + (int)(deltat / 3600), (int)((deltat % 3600) / 60)); + + return msgbuf; +} + +#if defined(SIGINFO) +/* + * statussig -- + * information message upon receipt of SIGINFO + */ +void +statussig(int notused) +{ + int save_errno = errno; + char *buf; + + buf = mktimeest(time(NULL)); + if (buf) + write(STDERR_FILENO, buf, strlen(buf)); + errno = save_errno; +} +#endif + +static void +flushtape(void) +{ + int i, blks, got; + long lastfirstrec; + struct slave_results returned; + + int siz = (char *)nextblock - (char *)slp->req; + + slp->req[trecno].count = 0; /* Sentinel */ + + if (dump_atomic_write( slp->fd, (char *)slp->req, siz) != siz) + quit("error writing command pipe: %s\n", strerror(errno)); + slp->sent = 1; /* we sent a request, read the response later */ + + lastfirstrec = slp->firstrec; + + if (++slp >= &slaves[SLAVES]) + slp = &slaves[0]; + + /* Read results back from next slave */ + if (slp->sent) { + if (dump_atomic_read( slp->fd, (char *)&returned, sizeof returned) + != sizeof returned) { + perror(" DUMP: error reading command pipe in master"); + dumpabort(0); + } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.unclen == returned.clen) + uncomprblks++; + slp->sent = 0; + + /* Check for errors or end of tape */ + if (got <= 0) { + /* Check for errors */ + if (got < 0) + tperror(-got); + else + msg("End of tape detected\n"); + + /* + * Drain the results, don't care what the values were. + * If we read them here then trewind won't... + */ + for (i = 0; i < SLAVES; i++) { + if (slaves[i].sent) { + if (dump_atomic_read( slaves[i].fd, + (char *)&returned, sizeof returned) + != sizeof returned) { + perror(" DUMP: error reading command pipe in master"); + dumpabort(0); + } + slaves[i].sent = 0; + } + } + + close_rewind(); + rollforward(); + return; + } + } + + blks = 0; + if (spcl.c_type != TS_END) { + for (i = 0; i < spcl.c_count; i++) + if (spcl.c_addr[i] != 0) + blks++; + } + slp->count = lastspclrec + blks + 1 - spcl.c_tapea; + slp->tapea = spcl.c_tapea; + slp->firstrec = lastfirstrec + ntrec; + slp->inode = curino; + nextblock = slp->tblock; + trecno = 0; + asize += tenths + returned.clen / density; + blockswritten += ntrec; + blocksthisvol += ntrec; + if (!pipeout && !unlimited) { + if (blocksperfiles && blocksperfiles[blocksperfiles_current]) { + if ( compressed ? (bytes_written - tapea_bytes + SLAVES * (writesize + sizeof(struct tapebuf))) >= (((long long)blocksperfiles[blocksperfiles_current]) * 1024) + : blocksthisvol >= blocksperfiles[blocksperfiles_current] ) { + close_rewind(); + startnewtape(0); + } + } + else if (asize > tsize) { + close_rewind(); + startnewtape(0); + } + } + timeest(); +} + +time_t +trewind(void) +{ + int f; + int got; + struct slave_results returned; + + for (f = 0; f < SLAVES; f++) { + /* + * Drain the results, but unlike EOT we DO (or should) care + * what the return values were, since if we detect EOT after + * we think we've written the last blocks to the tape anyway, + * we have to replay those blocks with rollforward. + * + * fixme: punt for now. + */ + if (slaves[f].sent) { + if (dump_atomic_read( slaves[f].fd, (char *)&returned, sizeof returned) + != sizeof returned) { + perror(" DUMP: error reading command pipe in master"); + dumpabort(0); + } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.unclen == returned.clen) + uncomprblks++; + slaves[f].sent = 0; + + if (got < 0) + tperror(-got); + + if (got == 0) { + msg("EOT detected in last 2 tape records!\n"); + msg("Use a longer tape, decrease the size estimate\n"); + quit("or use no size estimate at all.\n"); + } + } + (void) close(slaves[f].fd); + } + while (wait((int *)NULL) >= 0) /* wait for any signals from slaves */ + /* void */; + + if (!pipeout) { + + msg("Closing %s\n", tape); + +#ifdef RDUMP + if (host) { + rmtclose(); + while (rmtopen(tape, O_RDONLY) < 0) + sleep(10); + rmtclose(); + } + else +#endif + { + (void) close(tapefd); + if (!fifoout) { + while ((f = OPEN(tape, O_RDONLY)) < 0) + sleep (10); + (void) close(f); + } + } + } + return do_stats(); +} + + +void +close_rewind(void) +{ + int eot_code = 1; + (void)trewind(); + if (eot_script) { + msg("Launching %s\n", eot_script); + eot_code = system_command(eot_script, tape, tapeno); + } + if (eot_code != 0 && eot_code != 1) { + msg("Dump aborted by the end of tape script\n"); + dumpabort(0); + } + if (eot_code == 0) + return; + if (nexttape || Mflag) + return; + if (!nogripe) { + msg("Change Volumes: Mount volume #%d\n", tapeno+1); + broadcast("CHANGE DUMP VOLUMES!\7\7\n"); + } + while (!query("Is the new volume mounted and ready to go?")) + if (query("Do you want to abort?")) { + dumpabort(0); + /*NOTREACHED*/ + } +} + +void +rollforward(void) +{ + struct req *p, *q = NULL, *prev; + struct slave *tslp; + int i, size, savedtapea, got; + union u_spcl *ntb, *otb; + struct slave_results returned; +#ifdef __linux__ + int blks; + long lastfirstrec; +#endif + tslp = &slaves[SLAVES]; + ntb = (union u_spcl *)tslp->tblock[1]; + + /* + * Each of the N slaves should have requests that need to + * be replayed on the next tape. Use the extra slave buffers + * (slaves[SLAVES]) to construct request lists to be sent to + * each slave in turn. + */ + for (i = 0; i < SLAVES; i++) { + q = &tslp->req[1]; + otb = (union u_spcl *)slp->tblock; + + /* + * For each request in the current slave, copy it to tslp. + */ + + prev = NULL; + for (p = slp->req; p->count > 0; p += p->count) { + *q = *p; + if (p->dblk == 0) + *ntb++ = *otb++; /* copy the datablock also */ + prev = q; + q += q->count; + } + if (prev == NULL) + quit("rollforward: protocol botch"); + if (prev->dblk != 0) + prev->count -= 1; + else + ntb--; + q -= 1; + q->count = 0; + q = &tslp->req[0]; + if (i == 0) { + q->dblk = 0; + q->count = 1; + trecno = 0; + nextblock = tslp->tblock; + savedtapea = spcl.c_tapea; + spcl.c_tapea = slp->tapea; + startnewtape(0); + spcl.c_tapea = savedtapea; + lastspclrec = savedtapea - 1; + } + size = (char *)ntb - (char *)q; + if (dump_atomic_write( slp->fd, (char *)q, size) != size) { + perror(" DUMP: error writing command pipe"); + dumpabort(0); + } + slp->sent = 1; +#ifdef __linux__ + lastfirstrec = slp->firstrec; +#endif + if (++slp >= &slaves[SLAVES]) + slp = &slaves[0]; + + q->count = 1; + + if (prev->dblk != 0) { + /* + * If the last one was a disk block, make the + * first of this one be the last bit of that disk + * block... + */ + q->dblk = prev->dblk + + prev->count * (TP_BSIZE / DEV_BSIZE); + ntb = (union u_spcl *)tslp->tblock; + } else { + /* + * It wasn't a disk block. Copy the data to its + * new location in the buffer. + */ + q->dblk = 0; + *((union u_spcl *)tslp->tblock) = *ntb; + ntb = (union u_spcl *)tslp->tblock[1]; + } + } + slp->req[0] = *q; + nextblock = slp->tblock; + if (q->dblk == 0) { +#ifdef __linux__ + /* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */ + *(union u_spcl *)(*nextblock) = *(union u_spcl *)tslp->tblock; +#endif + nextblock++; + } + trecno = 1; + + /* + * Clear the first slaves' response. One hopes that it + * worked ok, otherwise the tape is much too short! + */ + if (slp->sent) { + if (dump_atomic_read( slp->fd, (char *)&returned, sizeof returned) + != sizeof returned) { + perror(" DUMP: error reading command pipe in master"); + dumpabort(0); + } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.clen == returned.unclen) + uncomprblks++; + slp->sent = 0; + + if (got < 0) + tperror(-got); + + if (got == 0) { + quit("EOT detected at start of the tape!\n"); + } + } + +#ifdef __linux__ + blks = 0; + if (spcl.c_type != TS_END) { + for (i = 0; i < spcl.c_count; i++) + if (spcl.c_addr[i] != 0) + blks++; + } + + slp->firstrec = lastfirstrec + ntrec; + slp->count = lastspclrec + blks + 1 - spcl.c_tapea; + slp->inode = curino; + asize += tenths + returned.clen / density; + blockswritten += ntrec; + blocksthisvol += ntrec; +#endif +} + +/* + * We implement taking and restoring checkpoints on the tape level. + * When each tape is opened, a new process is created by forking; this + * saves all of the necessary context in the parent. The child + * continues the dump; the parent waits around, saving the context. + * If the child returns X_REWRITE, then it had problems writing that tape; + * this causes the parent to fork again, duplicating the context, and + * everything continues as if nothing had happened. + */ +void +startnewtape(int top) +{ + int parentpid; + int childpid; + int status; + int waitpid; + char *p; + +#ifdef __linux__ + sigset_t sigs; + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); + sigprocmask(SIG_BLOCK, &sigs, NULL); +#else /* __linux__ */ +#ifdef sunos + void (*interrupt_save)(); +#else + sig_t interrupt_save; +#endif + interrupt_save = signal(SIGINT, SIG_IGN); +#endif /* __linux__ */ + + parentpid = getpid(); + tapea_volume = spcl.c_tapea; + tapea_bytes = bytes_written; + tstart_volume = time(NULL); + +restore_check_point: +#ifdef __linux__ + sigprocmask(SIG_UNBLOCK, &sigs, NULL); +#else + (void)signal(SIGINT, interrupt_save); +#endif + /* + * All signals are inherited... + */ + childpid = fork(); + if (childpid < 0) { + msg("Context save fork fails in parent %d\n", parentpid); + Exit(X_ABORT); + } + if (childpid != 0) { + /* + * PARENT: + * save the context by waiting + * until the child doing all of the work returns. + * don't catch the interrupt + */ +#ifdef __linux__ + sigprocmask(SIG_BLOCK, &sigs, NULL); +#else + signal(SIGINT, SIG_IGN); +#endif +#ifdef TDEBUG + msg("Tape: %d; parent process: %d child process %d\n", + tapeno+1, parentpid, childpid); +#endif /* TDEBUG */ + while ((waitpid = wait(&status)) != childpid) + if (waitpid != rshpid) + msg("Parent %d waiting for child %d has another child %d return\n", + parentpid, childpid, waitpid); + if (status & 0xFF) { + msg("Child %d returns LOB status %o\n", + childpid, status&0xFF); + } + status = (status >> 8) & 0xFF; +#ifdef TDEBUG + switch(status) { + case X_FINOK: + msg("Child %d finishes X_FINOK\n", childpid); + break; + case X_ABORT: + msg("Child %d finishes X_ABORT\n", childpid); + break; + case X_REWRITE: + msg("Child %d finishes X_REWRITE\n", childpid); + break; + default: + msg("Child %d finishes unknown %d\n", + childpid, status); + break; + } +#endif /* TDEBUG */ + switch(status) { + case X_FINOK: + Exit(X_FINOK); + case X_ABORT: + Exit(X_ABORT); + case X_REWRITE: + goto restore_check_point; + default: + msg("Bad return code from dump: %d\n", status); + Exit(X_ABORT); + } + /*NOTREACHED*/ + } else { /* we are the child; just continue */ +#ifdef TDEBUG + sleep(4); /* allow time for parent's message to get out */ + msg("Child on Tape %d has parent %d, my pid = %d\n", + tapeno+1, parentpid, getpid()); +#endif /* TDEBUG */ + /* + * If we have a name like "/dev/rmt0,/dev/rmt1", + * use the name before the comma first, and save + * the remaining names for subsequent volumes. + */ + tapeno++; /* current tape sequence */ + if (Mflag) { + snprintf(tape, MAXPATHLEN, "%s%03d", tapeprefix, tapeno); + tape[MAXPATHLEN - 1] = '\0'; + msg("Dumping volume %d on %s\n", tapeno, tape); + } + else if (nexttape || strchr(tapeprefix, ',')) { + if (nexttape && *nexttape) + tapeprefix = nexttape; + if ((p = strchr(tapeprefix, ',')) != NULL) { + *p = '\0'; + nexttape = p + 1; + } else + nexttape = NULL; + strncpy(tape, tapeprefix, MAXPATHLEN); + tape[MAXPATHLEN - 1] = '\0'; + msg("Dumping volume %d on %s\n", tapeno, tape); + } + if (blocksperfiles && blocksperfiles_current < *blocksperfiles) + blocksperfiles_current++; +#ifdef RDUMP + while ((tapefd = (host ? rmtopen(tape, O_WRONLY|O_CREAT|O_TRUNC) : pipeout ? + fileno(stdout) : + OPEN(tape, O_WRONLY|O_CREAT|O_TRUNC, 0666))) < 0) +#else + while ((tapefd = (pipeout ? fileno(stdout) : + OPEN(tape, O_WRONLY|O_CREAT|O_TRUNC, 0666))) < 0) +#endif + { + msg("Cannot open output \"%s\": %s\n", tape, + strerror(errno)); + if (!query("Do you want to retry the open?")) + dumpabort(0); + } +#ifdef RDUMP + if (!host) +#endif + { + struct mtget mt_stat; + magtapeout = ioctl(tapefd, MTIOCGET, (char *)&mt_stat) == 0; + /* + msg("Output is to %s\n", + magtapeout ? "tape" : "file/pipe"); + */ + } + + enslave(); /* Share open tape file descriptor with slaves */ + + asize = 0; + blocksthisvol = 0; + if (top) + newtape++; /* new tape signal */ + spcl.c_count = slp->count; + /* + * measure firstrec in TP_BSIZE units since restore doesn't + * know the correct ntrec value... + */ + spcl.c_firstrec = slp->firstrec; + spcl.c_volume++; + spcl.c_type = TS_TAPE; + spcl.c_flags |= DR_NEWHEADER; + spcl.c_ntrec = ntrec; + if (compressed) + spcl.c_flags |= DR_COMPRESSED; + writeheader((dump_ino_t)slp->inode); + spcl.c_flags &=~ DR_NEWHEADER; + msg("Volume %d started with block %ld at: %s", tapeno, + spcl.c_tapea, ctime(&tstart_volume)); + if (tapeno > 1) + msg("Volume %d begins with blocks from inode %d\n", + tapeno, slp->inode); + if (tapeno < (int)TP_NINOS) + volinfo[tapeno] = slp->inode; + } +} + +void +dumpabort(UNUSED(int signo)) +{ + + if (master != 0 && master != getpid()) + /* Signals master to call dumpabort */ + (void) kill(master, SIGTERM); + else { + killall(); + msg("The ENTIRE dump is aborted.\n"); + } +#ifdef RDUMP + rmtclose(); +#endif + Exit(X_ABORT); +} + +void +Exit(int status) +{ + +#ifdef TDEBUG + msg("pid = %d exits with status %d\n", getpid(), status); +#endif /* TDEBUG */ + exit(status); +} + +/* + * proceed - handler for SIGUSR2, used to synchronize IO between the slaves. + */ +static void +proceed(UNUSED(int signo)) +{ + if (ready) + siglongjmp(jmpbuf, 1); + caught++; +} + +void +enslave(void) +{ + int cmd[2]; +#ifdef LINUX_FORK_BUG + int i, j; +#else + int i, j; +#endif + + master = getpid(); + + { struct sigaction sa; + memset(&sa, 0, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = dumpabort; + sigaction(SIGTERM, &sa, NULL); /* Slave sends SIGTERM on dumpabort() */ + sa.sa_handler = sigpipe; + sigaction(SIGPIPE, &sa, NULL); + sa.sa_handler = proceed; + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR2, &sa, NULL); /* Slave sends SIGUSR2 to next slave */ + } + + for (i = 0; i < SLAVES; i++) { + if (i == slp - &slaves[0]) { + caught = 1; + } else { + caught = 0; + } + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd) < 0 || + (slaves[i].pid = fork()) < 0) + quit("too many slaves, %d (recompile smaller): %s\n", + i, strerror(errno)); + + slaves[i].fd = cmd[1]; + slaves[i].sent = 0; + if (slaves[i].pid == 0) { /* Slave starts up here */ + sigset_t sigs; + for (j = 0; j <= i; j++) + (void) close(slaves[j].fd); + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); /* Master handles this */ +#if defined(SIGINFO) + sigaddset(&sigs, SIGINFO); +#endif + sigprocmask(SIG_BLOCK, &sigs, NULL); + +#ifdef LINUX_FORK_BUG + if (dump_atomic_write( cmd[0], (char *) &i, sizeof i) + != sizeof i) + quit("master/slave protocol botched 3\n"); +#endif + doslave(cmd[0], +#ifdef WRITEDEBUG + i, +#endif + (slaves[i].pid == slp->pid)); + Exit(X_FINOK); + } + else + close(cmd[0]); + } + +#ifdef LINUX_FORK_BUG + /* + * Wait for all slaves to _actually_ start to circumvent a bug in + * Linux kernels >= 2.1.3 where a signal sent to a child that hasn't + * returned from fork() causes a SEGV in the child process + */ + for (i = 0; i < SLAVES; i++) + if (dump_atomic_read( slaves[i].fd, (char *) &j, sizeof j) != sizeof j) + quit("master/slave protocol botched 4\n"); +#endif + + for (i = 0; i < SLAVES; i++) + (void) dump_atomic_write( slaves[i].fd, + (char *) &slaves[(i + 1) % SLAVES].pid, + sizeof slaves[0].pid); + + master = 0; +} + +void +killall(void) +{ + int i; + + for (i = 0; i < SLAVES; i++) + if (slaves[i].pid > 0) { + (void) kill(slaves[i].pid, SIGKILL); + slaves[i].sent = 0; + } +} + +/* + * Synchronization - each process waits for a SIGUSR2 from the + * previous process before writing to the tape, and sends SIGUSR2 + * to the next process when the tape write completes. On tape errors + * a SIGUSR1 is sent to the master which then terminates all of the + * slaves. + */ +static void +doslave(int cmd, +#ifdef WRITEDEBUG + int slave_number, +#endif + int first) +{ + int nread; + int nextslave; + volatile int wrote = 0, size, eot_count, bufsize; + char * volatile buffer; +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + struct tapebuf * volatile comp_buf = NULL; + int compresult; + volatile int do_compress = !first; + unsigned long worklen; +#ifdef HAVE_LZO + lzo_align_t __LZO_MMODEL *LZO_WorkMem; +#endif +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + struct slave_results returns; +#ifdef __linux__ + errcode_t retval; +#endif +#ifdef USE_QFA + long long curtapepos; + union u_spcl *uspclptr; + struct s_spcl *spclptr; + /* long maxntrecs = 300000000 / (ntrec * 1024); last tested: 50 000 000 */ + long maxntrecs = 50000; /* every 50MB */ + long cntntrecs = maxntrecs; +#endif /* USE_QFA */ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigprocmask(SIG_BLOCK, &set, NULL); + sigemptyset(&set); + + /* + * Need our own seek pointer. + */ + (void) close(diskfd); + if ((diskfd = OPEN(disk, O_RDONLY)) < 0) + quit("slave couldn't reopen disk: %s\n", strerror(errno)); +#ifdef __linux__ +#ifdef BLKFLSBUF + (void)ioctl(diskfd, BLKFLSBUF, 0); +#endif + ext2fs_close(fs); + retval = dump_fs_open(disk, &fs); + if (retval) + quit("slave couldn't reopen disk: %s\n", error_message(retval)); +#endif /* __linux__ */ + + /* + * Need the pid of the next slave in the loop... + */ + if ((nread = dump_atomic_read( cmd, (char *)&nextslave, sizeof nextslave)) + != sizeof nextslave) { + quit("master/slave protocol botched - didn't get pid of next slave.\n"); + } + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + /* if we're doing a compressed dump, allocate the compress buffer */ + if (compressed) { + int bsiz = sizeof(struct tapebuf) + writesize; + /* Add extra space to deal with compression enlarging the buffer */ + if (TP_BSIZE > writesize/16 + 67) + bsiz += TP_BSIZE; + else + bsiz += writesize/16 + 67; + comp_buf = malloc(bsiz); + if (comp_buf == NULL) + quit("couldn't allocate a compress buffer.\n"); + if (zipflag == COMPRESS_ZLIB) + comp_buf->flags = COMPRESS_ZLIB; + else if (zipflag == COMPRESS_BZLIB) + comp_buf->flags = COMPRESS_BZLIB; + else if (zipflag == COMPRESS_LZO) { + comp_buf->flags = COMPRESS_LZO; + if (lzo_init() != LZO_E_OK) quit("lzo_init failed\n"); + } else + quit("internal error - unknown compression method: %d\n", zipflag); + } +#ifdef HAVE_LZO + LZO_WorkMem = malloc(LZO1X_1_MEM_COMPRESS); + if (!LZO_WorkMem) + quit("couldn't allocate a compress buffer.\n"); +#endif +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + + /* + * Get list of blocks to dump, read the blocks into tape buffer + */ + while ((nread = dump_atomic_read( cmd, (char *)slp->req, reqsiz)) == reqsiz) { + struct req *p = slp->req; + + for (trecno = 0; trecno < ntrec; + trecno += p->count, p += p->count) { + if (p->dblk) { /* read a disk block */ + bread(p->dblk, slp->tblock[trecno], + p->count * TP_BSIZE); + } else { /* read record from pipe */ + if (p->count != 1 || dump_atomic_read( cmd, + (char *)slp->tblock[trecno], + TP_BSIZE) != TP_BSIZE) + quit("master/slave protocol botched.\n"); + } + } + + /* Try to write the data... */ + wrote = 0; + eot_count = 0; + size = 0; + buffer = (char *) slp->tblock[0]; /* set write pointer */ + bufsize = writesize; /* length to write */ + returns.clen = returns.unclen = bufsize; + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + /* + * When writing a compressed dump, each block except + * the first one on each tape is written + * from struct tapebuf with an 4 byte prefix + * followed by the data. This can be less than + * writesize. Restore, on a short read, can compare the + * length read to the compressed length in the header + * to verify that the read was good. Blocks which don't + * compress well are written uncompressed. + * The first block written by each slave is not compressed + * and does not have a prefix. + */ + + if (compressed && do_compress) { + comp_buf->length = bufsize; + worklen = TP_BSIZE + writesize; + compresult = 1; +#ifdef HAVE_ZLIB + if (zipflag == COMPRESS_ZLIB) { + compresult = compress2(comp_buf->buf, + &worklen, + (char *)slp->tblock[0], + writesize, + compressed); + if (compresult == Z_OK) + compresult = 1; + else + compresult = 0; + } +#endif /* HAVE_ZLIB */ +#ifdef HAVE_BZLIB + if (zipflag == COMPRESS_BZLIB) { + unsigned int worklen2 = worklen; + compresult = BZ2_bzBuffToBuffCompress( + comp_buf->buf, + &worklen2, + (char *)slp->tblock[0], + writesize, + compressed, + 0, 30); + worklen = worklen2; + if (compresult == BZ_OK) + compresult = 1; + else + compresult = 0; + } + +#endif /* HAVE_BZLIB */ +#ifdef HAVE_LZO + if (zipflag == COMPRESS_LZO) { + lzo_uint worklen2 = worklen; + compresult = lzo1x_1_compress((char *)slp->tblock[0],writesize, + comp_buf->buf, + &worklen2, + LZO_WorkMem); + worklen = worklen2; + if (compresult == LZO_E_OK) + compresult = 1; + else + compresult = 0; + } +#endif /* HAVE_LZO */ + if (compresult && worklen <= ((unsigned long)writesize - 16)) { + /* write the compressed buffer */ + comp_buf->length = worklen; + comp_buf->compressed = 1; + buffer = (char *) comp_buf; + returns.clen = bufsize = worklen + sizeof(struct tapebuf); + } + else { + /* write the data uncompressed */ + comp_buf->length = writesize; + comp_buf->compressed = 0; + buffer = (char *) comp_buf; + returns.clen = bufsize = writesize + sizeof(struct tapebuf); + returns.unclen = returns.clen; + memcpy(comp_buf->buf, (char *)slp->tblock[0], writesize); + } + } + /* compress the remaining blocks if we're compressing */ + do_compress = compressed; +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + ready = 1; + if (!caught) + sigsuspend(&set); + } + ready = 0; + caught = 0; + +#ifdef USE_QFA + if (gTapeposfd >= 0) { + int i; + int foundone = 0; + + for (i = 0; (i < ntrec) && !foundone; ++i) { + uspclptr = (union u_spcl *)&slp->tblock[i]; + spclptr = &uspclptr->s_spcl; + if ((spclptr->c_magic == NFS_MAGIC) && + (spclptr->c_type == TS_INODE) && + (spclptr->c_date == gThisDumpDate) && + !(spclptr->c_dinode.di_mode & S_IFDIR) + ) { + foundone = 1; + /* if (cntntrecs >= maxntrecs) { only write every maxntrecs amount of data */ + cntntrecs = 0; + if (gtperr == 0) + gtperr = GetTapePos(&curtapepos); + /* if an error occured previously don't + * try again */ + if (gtperr == 0) { +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %ld\n", spclptr->c_inumber, curtapepos); +#endif + gtperr = MkTapeString(spclptr, curtapepos); + } + /* } */ + } + } + } +#endif /* USE_QFA */ + + while (eot_count < 10 && size < bufsize) { +#ifdef RDUMP + if (host) + wrote = rmtwrite(buffer + size, bufsize - size); + else +#endif + wrote = write(tapefd, buffer + size, bufsize - size); +#ifdef WRITEDEBUG + printf("slave %d wrote %d\n", slave_number, wrote); +#endif + if (wrote < 0 && errno != ENOSPC) + break; + if (wrote == 0 || (wrote < 0 && errno == ENOSPC)) + eot_count++; + else + size += wrote; + } + +#ifdef WRITEDEBUG + if (size != bufsize) + printf("slave %d only wrote %d out of %d bytes and gave up.\n", + slave_number, size, bufsize); +#endif + + /* + * Handle ENOSPC as an EOT condition. + */ + if (wrote < 0 && errno == ENOSPC) { + wrote = 0; + eot_count++; + } + + if (eot_count > 0) + returns.clen = returns.unclen = 0; + + /* + * pass errno back to master for special handling + */ + if (wrote < 0) + returns.unclen = -errno; + + /* + * pass size of data and size of write back to master + * (for EOT handling) + */ + (void) dump_atomic_write( cmd, (char *)&returns, sizeof returns); + + /* + * Signal the next slave to go. + */ + (void) kill(nextslave, SIGUSR2); +#ifdef USE_QFA + if (gTapeposfd >= 0) { + cntntrecs += ntrec; + } +#endif /* USE_QFA */ + } + if (nread != 0) + quit("error reading command pipe: %s\n", strerror(errno)); +} + +/* + * Since a read from a pipe may not return all we asked for, + * or a write may not write all we ask if we get a signal, + * loop until the count is satisfied (or error). + */ +static ssize_t +dump_atomic_read(int fd, char *buf, size_t count) +{ + int got, need = count; + + do { + while ((got = read(fd, buf, need)) > 0 && (need -= got) > 0) + buf += got; + } while (got == -1 && errno == EINTR); + return (got < 0 ? got : (ssize_t)count - need); +} + +/* + * Since a read from a pipe may not return all we asked for, + * or a write may not write all we ask if we get a signal, + * loop until the count is satisfied (or error). + */ +static ssize_t +dump_atomic_write(int fd, const char *buf, size_t count) +{ + int got, need = count; + + do { + while ((got = write(fd, buf, need)) > 0 && (need -= got) > 0) + buf += got; + } while (got == -1 && errno == EINTR); + return (got < 0 ? got : (ssize_t)count - need); +} + + +/* +int +SetLogicalPos(void) +{ + int err = 0; + struct mt_pos buf; + + buf.mt_op = MTSETDRVBUFFER; + buf.mt_count = MT_ST_BOOLEANS | MT_ST_SCSI2LOGICAL; + if (ioctl(tapefd, MTIOCTOP, &buf) == -1) { + err = errno; + msg("[%ld] error: %d (setting logical)\n", + (unsigned long)getpid(), err); + } + return err; +} +*/ + +#ifdef USE_QFA +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 +/* + * read the current tape position + */ +static int +GetTapePos(long long *pos) +{ + int err = 0; + +#ifdef RDUMP + if (host) { + *pos = (long long) rmtseek((OFF_T)0, (int)LSEEK_GET_TAPEPOS); + err = *pos < 0; + } + else +#endif + { + if (magtapeout) { + long mtpos; + *pos = 0; + err = (ioctl(tapefd, MTIOCPOS, &mtpos) < 0); + *pos = (long long)mtpos; + } + else { + *pos = LSEEK(tapefd, 0, SEEK_CUR); + err = (*pos < 0); + } + } + if (err) { + err = errno; + msg("[%ld] error: %d (getting tapepos: %lld)\n", getpid(), + err, *pos); + return err; + } + return err; +} + +static int +MkTapeString(struct s_spcl *spclptr, long long curtapepos) +{ + int err = 0; + +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %lld\n", spclptr->c_inumber, curtapepos); +#endif + + snprintf(gTps, sizeof(gTps), "%ld\t%d\t%lld\n", + (unsigned long)spclptr->c_inumber, + tapeno, + curtapepos); + gTps[sizeof(gTps) - 1] = '\0'; + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) { + err = errno; + warn("error writing tapepos file. (error %d)\n", errno); + } + return err; +} +#endif /* USE_QFA */ diff --git a/dump/traverse.c b/dump/traverse.c new file mode 100644 index 0000000..4104799 --- /dev/null +++ b/dump/traverse.c @@ -0,0 +1,1399 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: traverse.c,v 1.61 2004/07/01 09:14:49 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#ifdef __STDC__ +#include +#include +#endif +#include + +#include +#include +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#include +#elif defined sunos +#include + +#include +#include +#include +#else +#include +#include +#include +#endif /* __linux__ */ + +#include + +#include "dump.h" + +#define HASDUMPEDFILE 0x1 +#define HASSUBDIRS 0x2 + +#ifdef __linux__ +typedef u_quad_t fsizeT; +#else +#ifdef FS_44INODEFMT +typedef quad_t fsizeT; +#else +typedef long fsizeT; +#endif +#endif + +#ifdef __linux__ +static int searchdir __P((struct ext2_dir_entry *dp, int offset, + int blocksize, char *buf, void *private)); +#else +static int dirindir __P((dump_ino_t ino, daddr_t blkno, int level, long *size)); +static void dmpindir __P((dump_ino_t ino, daddr_t blk, int level, fsizeT *size)); +static int searchdir __P((dump_ino_t ino, daddr_t blkno, long size, long filesize)); +#endif +static void mapfileino __P((dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskipped)); + +#ifdef HAVE_EXT2_JOURNAL_INUM +#define ext2_journal_ino(sb) (sb->s_journal_inum) +#else +#define ext2_journal_ino(sb) (*((u_int32_t *)sb + 0x38)) +#endif +#ifndef HAVE_EXT2_INO_T +typedef ino_t ext2_ino_t; +#endif + +#ifndef EXT3_FEATURE_COMPAT_HAS_JOURNAL +#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 +#endif +#ifndef EXT2_FEATURE_INCOMPAT_FILETYPE +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#endif +#ifndef EXT3_FEATURE_INCOMPAT_RECOVER +#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 +#endif +#ifndef EXT3_FEATURE_INCOMPAT_JOURNAL_DEV +#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 +#endif + +#ifndef EXT2_LIB_FEATURE_INCOMPAT_SUPP +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT3_FEATURE_INCOMPAT_RECOVER | \ + EXT2_FEATURE_INCOMPAT_FILETYPE) +#endif +#ifndef EXT2_RESIZE_INO +#define EXT2_RESIZE_INO 7 +#endif +#ifndef EXT2_FT_UNKNOWN +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 +#define EXT2_FT_MAX 8 +#endif + +int dump_fs_open(const char *disk, ext2_filsys *fs) +{ + int retval; + + retval = ext2fs_open(disk, EXT2_FLAG_FORCE, 0, 0, unix_io_manager, fs); + if (!retval) { + struct ext2_super_block *es = (*fs)->super; + dump_ino_t journal_ino = ext2_journal_ino(es); + + if (es->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV){ + msg("This is a journal, not a filesystem!\n"); + retval = EXT2_ET_UNSUPP_FEATURE; + ext2fs_close(*fs); + } + else if ((retval = es->s_feature_incompat & + ~(EXT2_LIB_FEATURE_INCOMPAT_SUPP | + EXT3_FEATURE_INCOMPAT_RECOVER))) { + msg("Unsupported feature(s) 0x%x in filesystem\n", + retval); + retval = EXT2_ET_UNSUPP_FEATURE; + ext2fs_close(*fs); + } + else { + if (es->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL && + journal_ino) + do_exclude_ino(journal_ino, "journal inode"); + do_exclude_ino(EXT2_RESIZE_INO, "resize inode"); + } + } + return retval; +} + +/* + * This is an estimation of the number of TP_BSIZE blocks in the file. + * It estimates the number of blocks in files with holes by assuming + * that all of the blocks accounted for by di_blocks are data blocks + * (when some of the blocks are usually used for indirect pointers); + * hence the estimate may be high. + */ +long +blockest(struct dinode const *dp) +{ + long blkest, sizeest; + u_quad_t i_size; + + /* + * dp->di_size is the size of the file in bytes. + * dp->di_blocks stores the number of sectors actually in the file. + * If there are more sectors than the size would indicate, this just + * means that there are indirect blocks in the file or unused + * sectors in the last file block; we can safely ignore these + * (blkest = sizeest below). + * If the file is bigger than the number of sectors would indicate, + * then the file has holes in it. In this case we must use the + * block count to estimate the number of data blocks used, but + * we use the actual size for estimating the number of indirect + * dump blocks (sizeest vs. blkest in the indirect block + * calculation). + */ + blkest = howmany((u_quad_t)dp->di_blocks * 512, fs->blocksize) * (fs->blocksize / TP_BSIZE); + i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32); + sizeest = howmany(i_size, fs->blocksize) * (fs->blocksize / TP_BSIZE); + if (blkest > sizeest) + blkest = sizeest; +#ifdef __linux__ + if ((dp->di_mode & IFMT) == IFDIR) { + /* + * for directories, assume only half of space is filled + * with entries. + */ + blkest = blkest / 2; + sizeest = sizeest / 2; + } + if (i_size > (u_quad_t)fs->blocksize * NDADDR) { + /* calculate the number of indirect blocks on the dump tape */ + blkest += + howmany(sizeest - NDADDR * fs->blocksize / TP_BSIZE, + TP_NINDIR); + } +#else + if (i_size > sblock->fs_bsize * NDADDR) { + /* calculate the number of indirect blocks on the dump tape */ + blkest += + howmany(sizeest - NDADDR * sblock->fs_bsize / TP_BSIZE, + TP_NINDIR); + } +#endif + return (blkest + 1); +} + +/* Auxiliary macro to pick up files changed since previous dump. */ +#define CSINCE(dp, t) \ + ((dp)->di_ctime >= (t)) +#define MSINCE(dp, t) \ + ((dp)->di_mtime >= (t)) +#define CHANGEDSINCE(dp, t) \ + (CSINCE(dp, t) || MSINCE(dp, t)) + +/* The NODUMP_FLAG macro tests if a file has the nodump flag. */ +#ifdef UF_NODUMP +#define NODUMP_FLAG(dp) (!nonodump && (((dp)->di_flags & UF_NODUMP) == UF_NODUMP)) +#else +#define NODUMP_FLAG(dp) 0 +#endif + +/* The WANTTODUMP macro decides whether a file should be dumped. */ +#define WANTTODUMP(dp, ino) \ + (CHANGEDSINCE(dp, ((u_int32_t)spcl.c_ddate)) && \ + (!NODUMP_FLAG(dp)) && \ + (!exclude_ino(ino))) + +/* + * Determine if given inode should be dumped. "dp" must either point to a + * copy of the given inode, or be NULL (in which case it is fetched.) + */ +static void +mapfileino(dump_ino_t ino, struct dinode const *dp, long *tapesize, int *dirskipped) +{ + int mode; + + /* + * Skip inode if we've already marked it for dumping + */ + if (TSTINO(ino, usedinomap)) + return; + if (!dp) + dp = getino(ino); + if ((mode = (dp->di_mode & IFMT)) == 0) + return; +#ifdef __linux__ + if (dp->di_nlink == 0 || dp->di_dtime != 0) + return; +#endif + /* + * Put all dirs in dumpdirmap, inodes that are to be dumped in the + * used map. All inode but dirs who have the nodump attribute go + * to the usedinomap. + */ + SETINO(ino, usedinomap); + + if (mode == IFDIR) + SETINO(ino, dumpdirmap); + if (WANTTODUMP(dp, ino)) { + SETINO(ino, dumpinomap); + if (!MSINCE(dp, (u_int32_t)spcl.c_ddate)) + SETINO(ino, metainomap); + if (mode != IFREG && mode != IFDIR && mode != IFLNK) + *tapesize += 1; + else + *tapesize += blockest(dp); + return; + } + if (mode == IFDIR) { + if ( NODUMP_FLAG(dp) || exclude_ino(ino) ) + CLRINO(ino, usedinomap); + *dirskipped = 1; + } +} + +/* + * Dump pass 1. + * + * Walk the inode list for a filesystem to find all allocated inodes + * that have been modified since the previous dump time. Also, find all + * the directories in the filesystem. + */ +#ifdef __linux__ +int +mapfiles(UNUSED(dump_ino_t maxino), long *tapesize) +{ + ext2_ino_t ino; + int anydirskipped = 0; + ext2_inode_scan scan; + errcode_t err; + struct ext2_inode inode; + + /* + * We use libext2fs's inode scanning routines, which are particularly + * robust. (Note that getino cannot return an error.) + */ + err = ext2fs_open_inode_scan(fs, 0, &scan); + if (err) { + com_err(disk, err, "while opening inodes\n"); + exit(X_ABORT); + } + for (;;) { + err = ext2fs_get_next_inode(scan, &ino, &inode); + if (err == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) + continue; + if (err) { + com_err(disk, err, "while scanning inode #%ld\n", + (long)ino); + exit(X_ABORT); + } + if (ino == 0) + break; + + curino = ino; + mapfileino(ino, (struct dinode const *)&inode, tapesize, + &anydirskipped); + } + ext2fs_close_inode_scan(scan); + + /* + * Restore gets very upset if the root is not dumped, + * so ensure that it always is dumped. + */ + SETINO(ROOTINO, dumpinomap); + return (anydirskipped); +} +#else +int +mapfiles(dump_ino_t maxino, long *tapesize) +{ + dump_ino_t ino; + int anydirskipped = 0; + + for (ino = ROOTINO; ino < maxino; ino++) + mapfileino(ino, tapesize, &anydirskipped); + + /* + * Restore gets very upset if the root is not dumped, + * so ensure that it always is dumped. + */ + SETINO(ROOTINO, dumpinomap); + return (anydirskipped); +} +#endif /* __linux__ */ + +#ifdef __linux__ +int +maponefile(UNUSED(dump_ino_t maxino), long *tapesize, char *directory) +{ + errcode_t retval; + ext2_ino_t dir_ino; + char dir_name [MAXPATHLEN]; + int i, anydirskipped = 0; + + /* + * Mark every directory in the path as being dumped + */ + for (i = 0; i < (int)strlen (directory); i++) { + if (directory[i] == '/') { + strncpy (dir_name, directory, i); + dir_name[i] = '\0'; + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, + dir_name, &dir_ino); + if (retval) { + com_err(disk, retval, + "while translating %s", dir_name); + exit(X_ABORT); + } + mapfileino((dump_ino_t) dir_ino, 0, + tapesize, &anydirskipped); + } + } + /* + * Mark the final directory + */ + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, directory, &dir_ino); + if (retval) { + com_err(disk, retval, "while translating %s", directory); + exit(X_ABORT); + } + mapfileino((dump_ino_t)dir_ino, 0, tapesize, &anydirskipped); + + mapfileino(ROOTINO, 0, tapesize, &anydirskipped); + + /* + * Restore gets very upset if the root is not dumped, + * so ensure that it always is dumped. + */ + SETINO(ROOTINO, dumpdirmap); + return anydirskipped; +} +#endif /* __linux__ */ + +#ifdef __linux__ +struct mapfile_context { + long *tapesize; + int *anydirskipped; +}; + +static int +mapfilesindir(struct ext2_dir_entry *dirent, UNUSED(int offset), + UNUSED(int blocksize), UNUSED(char *buf), void *private) +{ + struct dinode const *dp; + int mode; + errcode_t retval; + struct mapfile_context *mfc; + ext2_ino_t ino; + + ino = dirent->inode; + mfc = (struct mapfile_context *)private; + dp = getino(dirent->inode); + + mapfileino(dirent->inode, dp, mfc->tapesize, mfc->anydirskipped); + + mode = dp->di_mode & IFMT; + if (mode == IFDIR && dp->di_nlink != 0 && dp->di_dtime == 0) { + if ((dirent->name[0] != '.' || ( dirent->name_len & 0xFF ) != 1) && + (dirent->name[0] != '.' || dirent->name[1] != '.' || + ( dirent->name_len & 0xFF ) != 2)) { + retval = ext2fs_dir_iterate(fs, ino, 0, NULL, + mapfilesindir, private); + if (retval) + return retval; + } + } + return 0; +} + +/* + * Dump pass 1. + * + * Walk the inode list for a filesystem to find all allocated inodes + * that have been modified since the previous dump time. Also, find all + * the directories in the filesystem. + */ +int +mapfilesfromdir(UNUSED(dump_ino_t maxino), long *tapesize, char *directory) +{ + errcode_t retval; + struct mapfile_context mfc; + ext2_ino_t dir_ino; + char dir_name [MAXPATHLEN]; + int i, anydirskipped = 0; + + /* + * Mark every directory in the path as being dumped + */ + for (i = 0; i < (int)strlen (directory); i++) { + if (directory[i] == '/') { + strncpy (dir_name, directory, i); + dir_name[i] = '\0'; + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, dir_name, + &dir_ino); + if (retval) { + com_err(disk, retval, "while translating %s", + dir_name); + exit(X_ABORT); + } + mapfileino(dir_ino, 0, tapesize, &anydirskipped); + } + } + /* + * Mark the final directory + */ + retval = ext2fs_namei(fs, ROOTINO, ROOTINO, directory, &dir_ino); + if (retval) { + com_err(disk, retval, "while translating %s", directory); + exit(X_ABORT); + } + mapfileino(dir_ino, 0, tapesize, &anydirskipped); + + mfc.tapesize = tapesize; + mfc.anydirskipped = &anydirskipped; + retval = ext2fs_dir_iterate(fs, dir_ino, 0, NULL, mapfilesindir, + (void *)&mfc); + + if (retval) { + com_err(disk, retval, "while mapping files in %s", directory); + exit(X_ABORT); + } + /* + * Ensure that the root inode actually appears in the file list + * for a subdir + */ + mapfileino(ROOTINO, 0, tapesize, &anydirskipped); + /* + * Restore gets very upset if the root is not dumped, + * so ensure that it always is dumped. + */ + SETINO(ROOTINO, dumpinomap); + return anydirskipped; +} +#endif + +#ifdef __linux__ +struct mapdirs_context { + int *ret; + int nodump; + long *tapesize; +}; +#endif + +/* + * Dump pass 2. + * + * Scan each directory on the filesystem to see if it has any modified + * files in it. If it does, and has not already been added to the dump + * list (because it was itself modified), then add it. If a directory + * has not been modified itself, contains no modified files and has no + * subdirectories, then it can be deleted from the dump list and from + * the list of directories. By deleting it from the list of directories, + * its parent may now qualify for the same treatment on this or a later + * pass using this algorithm. + */ +int +mapdirs(dump_ino_t maxino, long *tapesize) +{ + struct dinode *dp; + int isdir; + char *map; + dump_ino_t ino; +#ifndef __linux__ + int i; + long filesize; +#else + struct mapdirs_context mdc; +#endif + int ret, change = 0, nodump; + + isdir = 0; /* XXX just to get gcc to shut up */ + for (map = dumpdirmap, ino = 1; ino < maxino; ino++) { + if (((ino - 1) % NBBY) == 0) /* map is offset by 1 */ + isdir = *map++; + else + isdir >>= 1; + /* + * If dir has been removed from the used map, it's either + * because it had the nodump flag, or it herited it from + * its parent. A directory can't be in dumpinomap if not + * in usedinomap, but we have to go through it anyway + * to propagate the nodump attribute. + */ + nodump = (TSTINO(ino, usedinomap) == 0); + if ((isdir & 1) == 0 || + (TSTINO(ino, dumpinomap) && nodump == 0)) + continue; + dp = getino(ino); +#ifdef __linux__ + ret = 0; + mdc.ret = &ret; + mdc.nodump = nodump; + mdc.tapesize = tapesize; + ext2fs_dir_iterate(fs, ino, 0, NULL, searchdir, (void *) &mdc); +#else /* __linux__ */ + filesize = dp->di_size; + for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) { + if (dp->di_db[i] != 0) + ret |= searchdir(ino, dp->di_db[i], + (long)dblksize(sblock, dp, i), + filesize); + if (ret & HASDUMPEDFILE) + filesize = 0; + else + filesize -= sblock->fs_bsize; + } + for (i = 0; filesize > 0 && i < NIADDR; i++) { + if (dp->di_ib[i] == 0) + continue; + ret |= dirindir(ino, dp->di_ib[i], i, &filesize); + } +#endif /* __linux__ */ + if (ret & HASDUMPEDFILE) { + SETINO(ino, dumpinomap); + *tapesize += blockest(dp); + change = 1; + continue; + } + if (nodump) { + if (ret & HASSUBDIRS) + change = 1; /* subdirs have inherited nodump */ + CLRINO(ino, dumpdirmap); + } else if ((ret & HASSUBDIRS) == 0) { + if (!TSTINO(ino, dumpinomap)) { + CLRINO(ino, dumpdirmap); + change = 1; + } + } + } + return (change); +} + +#ifndef __linux__ +/* + * Read indirect blocks, and pass the data blocks to be searched + * as directories. Quit as soon as any entry is found that will + * require the directory to be dumped. + */ +static int +dirindir(dump_ino_t ino, daddr_t blkno, int ind_level, long *filesize) +{ + int ret = 0; + int i; + daddr_t idblk[MAXNINDIR]; + + bread(fsbtodb(sblock, blkno), (char *)idblk, (int)sblock->fs_bsize); + if (ind_level <= 0) { + for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { + blkno = idblk[i]; + if (blkno != 0) + ret |= searchdir(ino, blkno, sblock->fs_bsize, + *filesize); + if (ret & HASDUMPEDFILE) + *filesize = 0; + else + *filesize -= sblock->fs_bsize; + } + return (ret); + } + ind_level--; + for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) { + blkno = idblk[i]; + if (blkno != 0) + ret |= dirindir(ino, blkno, ind_level, filesize); + } + return (ret); +} +#endif /* !__linux__ */ + +/* + * Scan a disk block containing directory information looking to see if + * any of the entries are on the dump list and to see if the directory + * contains any subdirectories. + */ +#ifdef __linux__ +static int +searchdir(struct ext2_dir_entry *dp, UNUSED(int offset), + UNUSED(int blocksize), UNUSED(char *buf), void *private) +{ + struct mapdirs_context *mdc; + int *ret; + long *tapesize; + struct dinode *ip; + + mdc = (struct mapdirs_context *)private; + ret = mdc->ret; + tapesize = mdc->tapesize; + + if (dp->inode == 0) + return 0; + if (dp->name[0] == '.') { + if (( dp->name_len & 0xFF ) == 1) + return 0; + if (dp->name[1] == '.' && ( dp->name_len & 0xFF ) == 2) + return 0; + } + if (mdc->nodump) { + ip = getino(dp->inode); + if (TSTINO(dp->inode, dumpinomap)) { + CLRINO(dp->inode, dumpinomap); + *tapesize -= blockest(ip); + } + /* Add dir back to the dir map and remove from + * usedinomap to propagate nodump */ + if ((ip->di_mode & IFMT) == IFDIR) { + SETINO(dp->inode, dumpdirmap); + CLRINO(dp->inode, usedinomap); + *ret |= HASSUBDIRS; + } + } else { + if (TSTINO(dp->inode, dumpinomap)) { + *ret |= HASDUMPEDFILE; + if (*ret & HASSUBDIRS) + return DIRENT_ABORT; + } + if (TSTINO(dp->inode, dumpdirmap)) { + *ret |= HASSUBDIRS; + if (*ret & HASDUMPEDFILE) + return DIRENT_ABORT; + } + } + return 0; +} + +#else /* __linux__ */ + +static int +searchdir(dump_ino_t ino, daddr_t blkno, long size, long filesize) +{ + struct direct *dp; + long loc, ret = 0; + char dblk[MAXBSIZE]; + + bread(fsbtodb(sblock, blkno), dblk, (int)size); + if (filesize < size) + size = filesize; + for (loc = 0; loc < size; ) { + dp = (struct direct *)(dblk + loc); + if (dp->d_reclen == 0) { + msg("corrupted directory, inumber %d\n", ino); + break; + } + loc += dp->d_reclen; + if (dp->d_ino == 0) + continue; + if (dp->d_name[0] == '.') { + if (dp->d_name[1] == '\0') + continue; + if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') + continue; + } + if (TSTINO(dp->d_ino, dumpinomap)) { + ret |= HASDUMPEDFILE; + if (ret & HASSUBDIRS) + break; + } + if (TSTINO(dp->d_ino, dumpdirmap)) { + ret |= HASSUBDIRS; + if (ret & HASDUMPEDFILE) + break; + } + } + return (ret); +} +#endif /* __linux__ */ + +#ifdef __linux__ + +struct block_context { + ext2_ino_t ino; + int *buf; + int cnt; + int max; + int next_block; +}; + +/* + * Dump a block to the tape + */ +static int +dumponeblock(UNUSED(ext2_filsys fs), blk_t *blocknr, e2_blkcnt_t blockcnt, + UNUSED(blk_t ref_block), UNUSED(int ref_offset), void * private) +{ + struct block_context *p; + e2_blkcnt_t i; + + if (blockcnt < NDADDR) + return 0; + p = (struct block_context *)private; + for (i = p->next_block; i < blockcnt; i++) { + p->buf[p->cnt++] = 0; + if (p->cnt == p->max) { + blksout (p->buf, p->cnt, p->ino); + p->cnt = 0; + } + } + p->buf[p->cnt++] = *blocknr; + if (p->cnt == p->max) { + blksout (p->buf, p->cnt, p->ino); + p->cnt = 0; + } + p->next_block = blockcnt + 1; + return 0; +} +#endif + +/* + * Dump passes 3 and 4. + * + * Dump the contents of an inode to tape. + */ +void +dumpino(struct dinode *dp, dump_ino_t ino, int metaonly) +{ + unsigned long cnt; + fsizeT size, remaining; + char buf[TP_BSIZE]; + struct new_bsd_inode nbi; + int i; +#ifdef __linux__ + struct block_context bc; +#else + int ind_level; +#endif + u_quad_t i_size; + + if (metaonly) + i_size = 0; + else + i_size = dp->di_size + ((u_quad_t) dp->di_size_high << 32); + + if (newtape) { + newtape = 0; + dumpmap(dumpinomap, TS_BITS, ino); + } + CLRINO(ino, dumpinomap); +#ifdef __linux__ + memset(&nbi, 0, sizeof(nbi)); + nbi.di_mode = dp->di_mode; + nbi.di_nlink = dp->di_nlink; + nbi.di_ouid = dp->di_uid; + nbi.di_ogid = dp->di_gid; + nbi.di_size = i_size; + nbi.di_atime.tv_sec = dp->di_atime; + nbi.di_mtime.tv_sec = dp->di_mtime; + nbi.di_ctime.tv_sec = dp->di_ctime; + memmove(&nbi.di_db, &dp->di_db, (NDADDR + NIADDR) * sizeof(daddr_t)); + nbi.di_flags = dp->di_flags; + nbi.di_blocks = dp->di_blocks; + nbi.di_gen = dp->di_gen; + nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid; + nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid; + if (dp->di_file_acl) + msg("ACLs in inode #%ld won't be dumped\n", (long)ino); + memmove(&spcl.c_dinode, &nbi, sizeof(nbi)); +#else /* __linux__ */ + spcl.c_dinode = *dp; +#endif /* __linux__ */ + spcl.c_type = TS_INODE; + spcl.c_count = 0; + + if (metaonly && (dp->di_mode & S_IFMT)) { + spcl.c_flags |= DR_METAONLY; + spcl.c_count = 0; + writeheader(ino); + spcl.c_flags &= ~DR_METAONLY; + return; + } + + switch (dp->di_mode & S_IFMT) { + + case 0: + /* + * Freed inode. + */ + return; + +#ifdef __linux__ + case S_IFDIR: + msg("Warning: dumpino called on a directory (ino %d)\n", ino); + return; +#endif + + case S_IFLNK: + /* + * Check for short symbolic link. + */ +#ifdef __linux__ + if (i_size > 0 && + i_size < EXT2_N_BLOCKS * sizeof (daddr_t)) { + spcl.c_addr[0] = 1; + spcl.c_count = 1; + writeheader(ino); + memmove(buf, dp->di_db, (u_long)dp->di_size); + buf[dp->di_size] = '\0'; + writerec(buf, 0); + return; + } +#endif /* __linux__ */ +#ifdef FS_44INODEFMT + if (dp->di_size > 0 && + dp->di_size < sblock->fs_maxsymlinklen) { + spcl.c_addr[0] = 1; + spcl.c_count = 1; + writeheader(ino); + memmove(buf, dp->di_shortlink, (u_long)dp->di_size); + buf[dp->di_size] = '\0'; + writerec(buf, 0); + return; + } +#endif + /* fall through */ + +#ifndef __linux__ + case S_IFDIR: +#endif + case S_IFREG: + if (i_size) + break; + /* fall through */ + + case S_IFIFO: + case S_IFSOCK: + case S_IFCHR: + case S_IFBLK: + writeheader(ino); + return; + + default: + msg("Warning: undefined file type 0%o\n", dp->di_mode & IFMT); + return; + } + if (i_size > (u_quad_t)NDADDR * sblock->fs_bsize) +#ifdef __linux__ + cnt = NDADDR * EXT2_FRAGS_PER_BLOCK(fs->super); +#else + cnt = NDADDR * sblock->fs_frag; +#endif + else + cnt = howmany(i_size, sblock->fs_fsize); + blksout(&dp->di_db[0], cnt, ino); + if ((quad_t) (size = i_size - NDADDR * sblock->fs_bsize) <= 0) + return; +#ifdef __linux__ + bc.max = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super); + bc.buf = (int *)malloc (bc.max * sizeof (int)); + bc.cnt = 0; + bc.ino = ino; + bc.next_block = NDADDR; + + ext2fs_block_iterate2(fs, (ext2_ino_t)ino, 0, NULL, dumponeblock, (void *)&bc); + /* deal with holes at the end of the inode */ + if (i_size > ((u_quad_t)bc.next_block) * sblock->fs_fsize) { + remaining = i_size - ((u_quad_t)bc.next_block) * sblock->fs_fsize; + for (i = 0; i < (int)howmany(remaining, sblock->fs_fsize); i++) { + bc.buf[bc.cnt++] = 0; + if (bc.cnt == bc.max) { + blksout (bc.buf, bc.cnt, bc.ino); + bc.cnt = 0; + } + } + } + if (bc.cnt > 0) { + blksout (bc.buf, bc.cnt, bc.ino); + } + free(bc.buf); +#else + for (ind_level = 0; ind_level < NIADDR; ind_level++) { + dmpindir(ino, dp->di_ib[ind_level], ind_level, &size); + if (size <= 0) + return; + } +#endif +} + +#ifdef __linux__ + +struct convert_dir_context { + char *buf; + int prev_offset; + int offset; + int bs; +}; + +/* + * This function converts an ext2fs directory entry to the BSD format. + * + * Basically, it adds a null-character at the end of the name, recomputes the + * size of the entry, and creates it in a temporary buffer + */ +static int +convert_dir(struct ext2_dir_entry *dirent, UNUSED(int offset), + UNUSED(int blocksize), UNUSED(char *buf), void *private) +{ + struct convert_dir_context *p; + struct direct *dp; + int reclen; + + p = (struct convert_dir_context *)private; + + reclen = EXT2_DIR_REC_LEN((dirent->name_len & 0xFF) + 1); + if (((p->offset + reclen - 1) / p->bs) != (p->offset / p->bs)) { + dp = (struct direct *)(p->buf + p->prev_offset); + dp->d_reclen += p->bs - (p->offset % p->bs); + p->offset += p->bs - (p->offset % p->bs); + } + + dp = (struct direct *)(p->buf + p->offset); + dp->d_ino = dirent->inode; + dp->d_reclen = reclen; + dp->d_namlen = dirent->name_len & 0xFF; + switch ((dirent->name_len & 0xFF00) >> 8) { + default: + dp->d_type = DT_UNKNOWN; + break; + case EXT2_FT_REG_FILE: + dp->d_type = DT_REG; + break; + case EXT2_FT_DIR: + dp->d_type = DT_DIR; + break; + case EXT2_FT_CHRDEV: + dp->d_type = DT_CHR; + break; + case EXT2_FT_BLKDEV: + dp->d_type = DT_BLK; + break; + case EXT2_FT_FIFO: + dp->d_type = DT_FIFO; + break; + case EXT2_FT_SOCK: + dp->d_type = DT_SOCK; + break; + case EXT2_FT_SYMLINK: + dp->d_type = DT_LNK; + break; + } + strncpy(dp->d_name, dirent->name, dp->d_namlen); + dp->d_name[dp->d_namlen] = '\0'; + p->prev_offset = p->offset; + p->offset += reclen; + + return 0; +} + +/* + * Dump pass 3 + * + * Dumps a directory to tape after converting it to the BSD format + */ +void +dumpdirino(struct dinode *dp, dump_ino_t ino) +{ + fsizeT size; + char buf[TP_BSIZE]; + struct new_bsd_inode nbi; + struct convert_dir_context cdc; + errcode_t retval; + struct ext2_dir_entry *de; + fsizeT dir_size; + + if (newtape) { + newtape = 0; + dumpmap(dumpinomap, TS_BITS, ino); + } + CLRINO(ino, dumpinomap); + + /* + * Convert the directory to the BSD format + */ + /* Allocate a buffer for the conversion (twice the size of the + ext2fs directory to avoid problems ;-) */ + cdc.buf = (char *)malloc(dp->di_size * 2 * sizeof(char)); + if (cdc.buf == NULL) + err(1, "Cannot allocate buffer to convert directory #%lu\n", + (unsigned long)ino); + cdc.offset = 0; + cdc.prev_offset = 0; + cdc.bs = MIN(DIRBLKSIZ, TP_BSIZE); + /* Do the conversion */ + retval = ext2fs_dir_iterate(fs, (ext2_ino_t)ino, 0, NULL, convert_dir, (void *)&cdc); + if (retval) { + com_err(disk, retval, "while converting directory #%ld\n", (long)ino); + exit(X_ABORT); + } + /* Fix the last entry */ + if ((cdc.offset % cdc.bs) != 0) { + de = (struct ext2_dir_entry *)(cdc.buf + cdc.prev_offset); + de->rec_len += cdc.bs - (cdc.offset % cdc.bs); + cdc.offset += cdc.bs - (cdc.offset % cdc.bs); + } + + dir_size = cdc.offset; + +#ifdef __linux__ + memset(&nbi, 0, sizeof(nbi)); + nbi.di_mode = dp->di_mode; + nbi.di_nlink = dp->di_nlink; + nbi.di_ouid = dp->di_uid; + nbi.di_ogid = dp->di_gid; + nbi.di_size = dir_size; /* (u_quad_t)dp->di_size; */ + nbi.di_atime.tv_sec = dp->di_atime; + nbi.di_mtime.tv_sec = dp->di_mtime; + nbi.di_ctime.tv_sec = dp->di_ctime; + memmove(&nbi.di_db, &dp->di_db, (NDADDR + NIADDR) * sizeof(daddr_t)); + nbi.di_flags = dp->di_flags; + nbi.di_blocks = dp->di_blocks; + nbi.di_gen = dp->di_gen; + nbi.di_uid = (((int32_t)dp->di_uidhigh) << 16) | dp->di_uid; + nbi.di_gid = (((int32_t)dp->di_gidhigh) << 16) | dp->di_gid; + if (dp->di_file_acl) + msg("ACLs in inode #%ld won't be dumped\n", (long)ino); + memmove(&spcl.c_dinode, &nbi, sizeof(nbi)); +#else /* __linux__ */ + spcl.c_dinode = *dp; +#endif /* __linux__ */ + spcl.c_type = TS_INODE; + spcl.c_count = 0; + switch (dp->di_mode & S_IFMT) { + + case 0: + /* + * Freed inode. + */ + return; + + case S_IFDIR: + if (dir_size > 0) + break; + msg("Warning: size of directory inode #%d is <= 0 (%d)!\n", + ino, dir_size); + return; + + default: + msg("Warning: dumpdirino called with file type 0%o (inode #%d)\n", + dp->di_mode & IFMT, ino); + return; + } + for (size = 0; size < dir_size; size += TP_BSIZE) { + spcl.c_addr[0] = 1; + spcl.c_count = 1; + writeheader(ino); + memmove(buf, cdc.buf + size, TP_BSIZE); + writerec(buf, 0); + spcl.c_type = TS_ADDR; + } + + (void)free(cdc.buf); +} +#endif /* __linux__ */ + +#ifndef __linux__ +/* + * Read indirect blocks, and pass the data blocks to be dumped. + */ +static void +dmpindir(dump_ino_t ino, daddr_t blk, int ind_level, fsizeT *size) +{ + int i, cnt; +#ifdef __linux__ + int max; + blk_t *swapme; +#endif + daddr_t idblk[MAXNINDIR]; + + if (blk != 0) { + bread(fsbtodb(sblock, blk), (char *)idblk, (int) sblock->fs_bsize); +#ifdef __linux__ + /* + * My RedHat 4.0 system doesn't have these flags; I haven't + * upgraded e2fsprogs yet + */ +#if defined(EXT2_FLAG_SWAP_BYTES) + if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || + (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) +#endif + { + max = sblock->fs_bsize >> 2; + swapme = (blk_t *) idblk; + for (i = 0; i < max; i++, swapme++) + *swapme = ext2fs_swab32(*swapme); + } +#endif /* __linux__ */ + else + memset(idblk, 0, (int)sblock->fs_bsize); + if (ind_level <= 0) { + if (*size < NINDIR(sblock) * sblock->fs_bsize) + cnt = howmany(*size, sblock->fs_fsize); + else +#ifdef __linux__ + cnt = NINDIR(sblock) * EXT2_FRAGS_PER_BLOCK(fs->super); +#else + cnt = NINDIR(sblock) * sblock->fs_frag; +#endif + *size -= NINDIR(sblock) * sblock->fs_bsize; + blksout(&idblk[0], cnt, ino); + return; + } + ind_level--; + for (i = 0; i < NINDIR(sblock); i++) { + dmpindir(ino, idblk[i], ind_level, size); + if (*size <= 0) + return; + } +} +#endif + +/* + * Collect up the data into tape record sized buffers and output them. + */ +void +blksout(blk_t *blkp, int frags, dump_ino_t ino) +{ + blk_t *bp; + int i, j, count, blks, tbperdb; + + blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); + tbperdb = sblock->fs_bsize >> tp_bshift; + for (i = 0; i < blks; i += TP_NINDIR) { + if (i + TP_NINDIR > blks) + count = blks; + else + count = i + TP_NINDIR; + for (j = i; j < count; j++) + if (blkp[j / tbperdb] != 0) + spcl.c_addr[j - i] = 1; + else + spcl.c_addr[j - i] = 0; + spcl.c_count = count - i; + writeheader(ino); + bp = &blkp[i / tbperdb]; + for (j = i; j < count; j += tbperdb, bp++) { + if (*bp != 0) { + if (j + tbperdb <= count) + dumpblock(*bp, (int)sblock->fs_bsize); + else + dumpblock(*bp, (count - j) * TP_BSIZE); + } + } + spcl.c_type = TS_ADDR; + } +} + +/* + * Dump a map to the tape. + */ +void +dumpmap(char *map, int type, dump_ino_t ino) +{ + int i; + char *cp; + + spcl.c_type = type; + spcl.c_count = howmany(mapsize * sizeof(char), TP_BSIZE); + writeheader(ino); + for (i = 0, cp = map; i < spcl.c_count; i++, cp += TP_BSIZE) + writerec(cp, 0); +} + +#if defined(__linux__) && !defined(int32_t) +#define int32_t __s32 +#endif + +/* + * Compute and fill in checksum information. + */ +void +mkchecksum(union u_spcl *tmpspcl) +{ + int32_t sum, cnt, *lp; + + tmpspcl->s_spcl.c_checksum = 0; + lp = (int32_t *)&tmpspcl->s_spcl; + sum = 0; + cnt = sizeof(union u_spcl) / (4 * sizeof(int32_t)); + while (--cnt >= 0) { + sum += *lp++; + sum += *lp++; + sum += *lp++; + sum += *lp++; + } + tmpspcl->s_spcl.c_checksum = CHECKSUM - sum; +} + +/* + * Write a header record to the dump tape. + */ +void +writeheader(dump_ino_t ino) +{ + spcl.c_inumber = ino; + spcl.c_magic = NFS_MAGIC; + mkchecksum((union u_spcl *)&spcl); + writerec((char *)&spcl, 1); +} + +#ifdef __linux__ +struct dinode * +getino(dump_ino_t inum) +{ + static struct dinode dinode; + errcode_t err; + + curino = inum; + err = ext2fs_read_inode(fs, (ext2_ino_t)inum, (struct ext2_inode *) &dinode); + if (err) { + com_err(disk, err, "while reading inode #%ld\n", (long)inum); + exit(X_ABORT); + } + return &dinode; +} +#else /* __linux__ */ +struct dinode * +getino(dump_ino_t inum) +{ + static daddr_t minino, maxino; + static struct dinode inoblock[MAXINOPB]; + + curino = inum; + if (inum >= minino && inum < maxino) + return (&inoblock[inum - minino]); + bread(fsbtodb(sblock, ino_to_fsba(sblock, inum)), (char *)inoblock, + (int)sblock->fs_bsize); + minino = inum - (inum % INOPB(sblock)); + maxino = minino + INOPB(sblock); + return (&inoblock[inum - minino]); +} +#endif /* __linux__ */ + +/* + * Read a chunk of data from the disk. + * Try to recover from hard errors by reading in sector sized pieces. + * Error recovery is attempted at most BREADEMAX times before seeking + * consent from the operator to continue. + */ +int breaderrors = 0; + +void +bread(ext2_loff_t blkno, char *buf, int size) +{ + int cnt, i; + +loop: +#ifdef __linux__ + if (ext2fs_llseek(diskfd, (blkno << dev_bshift), 0) != + (blkno << dev_bshift)) +#else + if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) != + ((off_t)blkno << dev_bshift)) +#endif + msg("bread: lseek fails\n"); + if ((cnt = read(diskfd, buf, size)) == size) + return; + if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) { + /* + * Trying to read the final fragment. + * + * NB - dump only works in TP_BSIZE blocks, hence + * rounds `dev_bsize' fragments up to TP_BSIZE pieces. + * It should be smarter about not actually trying to + * read more than it can get, but for the time being + * we punt and scale back the read only when it gets + * us into trouble. (mkm 9/25/83) + */ + size -= dev_bsize; + goto loop; + } + if (cnt == -1) + msg("read error from %s: %s: [block %d, ext2blk %d]: count=%d\n", + disk, strerror(errno), blkno, + dbtofsb(sblock, blkno), size); + else + msg("short read error from %s: [block %d, ext2blk %d]: count=%d, got=%d\n", + disk, blkno, dbtofsb(sblock, blkno), size, cnt); + if (breademax && ++breaderrors > breademax) { + msg("More than %d block read errors from %d\n", + breademax, disk); + broadcast("DUMP IS AILING!\n"); + msg("This is an unrecoverable error.\n"); + if (!query("Do you want to attempt to continue?")){ + dumpabort(0); + /*NOTREACHED*/ + } else + breaderrors = 0; + } + /* + * Zero buffer, then try to read each sector of buffer separately. + */ + memset(buf, 0, size); + for (i = 0; i < size; i += dev_bsize, buf += dev_bsize, blkno++) { +#ifdef __linux__ + if (ext2fs_llseek(diskfd, (blkno << dev_bshift), 0) != + (blkno << dev_bshift)) +#else + if (lseek(diskfd, ((off_t)blkno << dev_bshift), 0) != + ((off_t)blkno << dev_bshift)) +#endif + msg("bread: lseek2 fails!\n"); + if ((cnt = read(diskfd, buf, (int)dev_bsize)) == dev_bsize) + continue; + if (cnt == -1) { + msg("read error from %s: %s: [sector %d, ext2blk %d]: count=%d\n", + disk, strerror(errno), blkno, + dbtofsb(sblock, blkno), dev_bsize); + continue; + } + msg("short read error from %s: [sector %d, ext2blk %d]: count=%d, got=%d\n", + disk, blkno, dbtofsb(sblock, blkno), dev_bsize, cnt); + } +} diff --git a/dump/unctime.c b/dump/unctime.c new file mode 100644 index 0000000..684719d --- /dev/null +++ b/dump/unctime.c @@ -0,0 +1,130 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: unctime.c,v 1.16 2003/03/30 15:40:37 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#ifdef __STDC__ +#include +#include +#endif + +#include +#include + +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#endif + +#include "dump.h" + +/* + * Convert a ctime(3) format string into a system format date. + * Return the date thus calculated. + * + * Return -1 if the string is not in ctime format. + */ + +/* + * Offsets into the ctime string to various parts. + */ + +#define E_MONTH 4 +#define E_DAY 8 +#define E_HOUR 11 +#define E_MINUTE 14 +#define E_SECOND 17 +#define E_YEAR 20 +#define E_TZOFFSET 25 + +static int lookup __P((const char *)); + + +time_t +unctime(const char *str) +{ + struct tm then; + char dbuf[32]; + time_t rtime; + int tzoffset; + + (void) strncpy(dbuf, str, sizeof(dbuf) - 1); + dbuf[sizeof(dbuf) - 1] = '\0'; + dbuf[E_MONTH+3] = '\0'; + if ((then.tm_mon = lookup(&dbuf[E_MONTH])) < 0) + return (-1); + then.tm_mday = atoi(&dbuf[E_DAY]); + then.tm_hour = atoi(&dbuf[E_HOUR]); + then.tm_min = atoi(&dbuf[E_MINUTE]); + then.tm_sec = atoi(&dbuf[E_SECOND]); + then.tm_year = atoi(&dbuf[E_YEAR]) - 1900; + then.tm_isdst = -1; + if (strlen(str) >= E_TZOFFSET+5) { + rtime = timegm(&then); + /* add timezone offset */ + tzoffset = atoi(&dbuf[E_TZOFFSET]); + rtime -= (tzoffset / 100 * 3600) + (tzoffset % 100) * 60; + } else { + rtime = timelocal(&then); + } + return(rtime); +} + +static char months[] = + "JanFebMarAprMayJunJulAugSepOctNovDec"; + +static int +lookup(const char *str) +{ + const char *cp, *cp2; + + for (cp = months, cp2 = str; *cp != '\0'; cp += 3) + if (strncmp(cp, cp2, 3) == 0) + return((cp-months) / 3); + return(-1); +} diff --git a/examples/cron_dump_to_disk/README b/examples/cron_dump_to_disk/README new file mode 100644 index 0000000..5301f17 --- /dev/null +++ b/examples/cron_dump_to_disk/README @@ -0,0 +1,31 @@ +Here is how to use these backup scripts: + +1. Create a separate backup partition big enough to hold all the filesystems you want to backup + any changes. Preferably, get a big inexpensive ide drive, and dedicate it as a backup drive. + +2. Create the mount point for the partition as /backup (otherwise, modify the config parameters at the top of the scripts). + +3. Mount the partition read-write, cd into /backup, and extract the backupskel.tar.gz there. This will create the directory structure needed by the scripts. + +4. Set the partition to be mounted as read-only in your /etc/fstab. This will protect your precious backup from software crashes. + +5. Copy the backup scripts "backup" and "backup_rotate" to a suitable directory in cron's path; "/usr/bin" is a good location. alternatively, you can place them anywhere, and modify the crontab entries to match, or run it manually. + +6. Modify your /etc/crontab file to add these entries, and be sure to modify the times to suit your preferences, and the performance of your machine: + +----------%<---------------------------------%<-------------------------------- + +# Perform Nightly Backup (nightly incremental + weekly full + monthly full) +02 06 * * 1-6 root backup_rotate ; nice -1 backup inc +02 06 * * sun root backup_rotate ; nice -1 backup full +07 00 01 * * root backup_rotate monthly ; backup full nodumpdate + +----------%<---------------------------------%<-------------------------------- + +Any questions? Send me and email to getnito@yahoo.com. + +And that is it. Have fun! + +-- +nito + +getnito@yahoo.com diff --git a/examples/cron_dump_to_disk/backup b/examples/cron_dump_to_disk/backup new file mode 100755 index 0000000..da6bda6 --- /dev/null +++ b/examples/cron_dump_to_disk/backup @@ -0,0 +1,179 @@ +#!/bin/bash +# +# This script will make a simple backup of the most critical partitions, +# using the "dump" facility, into the backup partition. It will stop the +# webserver, and recurse the sites directories making a tar mini-backup of +# the database dirs. It will the restart the webserver, and start the +# "dump" backup. +# + +if [ "$2" = "nodumpdate" ]; then + UPDATEDDATE="" +else + UPDATEDDATE="-u" +fi + +if [ "$1" = "full" ]; then + DLEVEL="0" + BTYPE="full" +elif [ "$1" = "inc" ]; then + DLEVEL="1" + BTYPE="inc" +else + echo "Usage: $0 full|inc [nodumpdate]" + exit 1 +fi + + +# +# Configuration Parameters +# + +BACKUPPART="/backup" +BACKUPDIR="current" +DUMPLOGARCH="$BACKUPPART/backup.dump.log.gz" +FSTODUMP="/ /var /home /mnt/hdb1 /usr" +DUMPFILESMODE="0644" +DUMPFILESOWN="root.root" + +# +# Start +# + +echo +echo "#####################################################################" +echo "Starting backup." +echo "#####################################################################" +echo + + +# +# Make full system backup +# + +echo "Phase 1: ### Full System Dump Backup ###" +echo "Phase 1: Using backup partition: $BACKUPPART" +echo "Phase 1: Filesystems to dump: $FSTODUMP" + +echo -n "Phase 1: Remounting backup partition read-write ... " +if ( mount $BACKUPPART -o remount,rw &> /dev/null ) then + echo "done." +else + echo "failure!" + echo "Phase 1: There were problems remounting $BACKUPPART in read-write mode!" + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 +fi + +echo -n "Phase 1: Checking backup partition for correct dir structure ... " +if [ -d $BACKUPPART/$BACKUPDIR -a -w $BACKUPPART/$BACKUPDIR ]; then + echo "done." + + echo -n "Phase 1: Checking backup partition for available space ... " + SREQ=`for i in $FSTODUMP;do dump -$DLEVEL -S $i 2> /dev/null;done|awk '{x=x+$1/1048576} END {printf "%6.0f\n", x}'` + SAVAILFREE=`df --block-size=1048576 |grep -Ew $BACKUPPART|awk '{printf "%6.0f\n", $4}'` + SAVAILDEL=`du -s --block-size=1048576 $BACKUPPART/$BACKUPDIR/. |awk '{printf "%6.0f\n", $1}'` + SAVAIL=`expr $SAVAILFREE + $SAVAILDEL` + + if [ `expr $SAVAIL - $SREQ` -gt "0" ]; then + echo "done." + echo "Phase 1: Available: $SAVAIL MB Required: $SREQ MB." + else + echo "no enough space!" + echo "Phase 1: There is not enough space left in $BACKUPPART for the backup!" + echo "Phase 1: Available: $SAVAIL MB Required: $SREQ MB." + echo -n "Phase 1: Remounting backup partition read-only ... " + if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." + else + echo "failure!" + echo "Phase 1: There were problems remounting $BACKUPPART in read-only mode!" + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 + fi + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 + fi + + echo -n "Phase 1: Deleting old files ... " + if [ `ls -la $BACKUPPART/$BACKUPDIR/|wc -l` -gt "3" ]; then + rm -f $BACKUPPART/$BACKUPDIR/* &> /dev/null + echo "done." + else + echo "no old files to delete." + fi + + echo "Phase 1: Dumping filesystems ... " + for FS in $FSTODUMP + do + if [ "$FS" = "/" ]; then + FSNAME="root" + else + FSNAME=`echo $FS|tr / _|cut -b 2-` + fi + sync + echo -n "Phase 1: Starting dump of $FSNAME ( $FS ) ... " + if ( dump -$DLEVEL $UPDATEDDATE -z -M -s 27306 -f $BACKUPPART/$BACKUPDIR/$FSNAME.$BTYPE. $FS &> $BACKUPPART/$BACKUPDIR/$FSNAME.log ) then + echo "done." + else + echo "problems!" + echo "Phase 1: There where problems with the dump of $FSNAME ( $FS )." + echo "Phase 1: Check logfile $BACKUPPART/$BACKUPDIR/$FSNAME.log for more info" + echo "Phase 1: Also check log archive file $DUMPLOGARCH." + fi + cat $BACKUPPART/$BACKUPDIR/$FSNAME.log |gzip >> $DUMPLOGARCH + echo "-------------------------------------------------------------------------------" |gzip >> $DUMPLOGARCH + done + + echo -n "Phase 1: Setting ownership and permissions of dump files ... " + chmod $DUMPFILESMODE $BACKUPPART/$BACKUPDIR/* $DUMPLOGARCH &> /dev/null + chown $DUMPFILESOWN $BACKUPPART/$BACKUPDIR/* $DUMPLOGARCH &> /dev/null + echo "done." + + echo -n "Phase 1: Compressing dump log files ... " + gzip $BACKUPPART/$BACKUPDIR/*.log &> /dev/null + echo "done." + sync + +else + echo "problems!" + echo "Phase 1: There are problems with the directory structure." + echo "Phase 1: Check dirs: $BACKUPPART/$BACKUPDIR" + echo -n "Phase 1: Remounting backup partition read-only ... " + if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." + else + echo "failure!" + echo "Phase 1: There were problems remounting $BACKUPPART in read-only mode!" + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 + fi + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 +fi + +echo -n "Phase 1: Remounting backup partition read-only ... " +if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." +else + echo "failure!" + echo "Phase 1: There were problems remounting $BACKUPPART in read-only mode!" + echo "Phase 1: Aborting Full System Dump Backup." + echo "Phase 1: Aborted, done." + echo "-------------------------------------------------------------------------------" + exit 1 +fi + +echo "Phase 1: End of Full System Dump Backup." +echo "Phase 1: Done." +echo "-------------------------------------------------------------------------------" diff --git a/examples/cron_dump_to_disk/backup_rotate b/examples/cron_dump_to_disk/backup_rotate new file mode 100755 index 0000000..2e8eeb9 --- /dev/null +++ b/examples/cron_dump_to_disk/backup_rotate @@ -0,0 +1,90 @@ +#!/bin/bash +# +# This script will redirect the backup directory to implement desired backup +# schedules. +# +# Currently we will use just a seven day format were we just move a link +# that represents the backup directory, to point to the day of the week. +# + +# +# Configuration Parameters +# + +if [ "$1" = "monthly" ]; then + REALDIR="monthly" +else + REALDIR=`date +%A` +fi + +BACKUPPART="/backup" +BACKUPDIR="current" + +echo "### Start of Backup Rotation ###" +echo "Using backup partition: $BACKUPPART" + +echo -n "Remounting backup partition read-write ... " +if ( mount $BACKUPPART -o remount,rw &> /dev/null ) then + echo "done." +else + echo "failure!" + echo " There were problems remounting $BACKUPPART in read-write mode!" + echo "Rotation not made!" + echo "### End of Backup Rotation ###" + exit 1 +fi + +echo -n "Checking that no directory named \"$BACKUPDIR\" exists ... " +if [ -d $BACKUPPART/$BACKUPDIR -a ! -L $BACKUPPART/$BACKUPDIR ]; then + echo "failure!" + echo " Directory \"$BACKUPDIR\" exists. Can't create link!" + echo "Rotation not made!" + + echo -n "Remounting backup partition read-only ... " + if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." + else + echo "failure!" + echo " There were problems remounting $BACKUPPART in read-only mode!" + echo "### End of Backup Rotation ###" + exit 1 + fi + echo "### End of Backup Rotation ###" + exit 1 +else + echo "done." +fi + +cd $BACKUPPART + +echo -n "Creating link: $BACKUPDIR --> $REALDIR ... " +if ( ln -snf $REALDIR $BACKUPDIR &> /dev/null ) then + echo "done." +else + echo "failure!" + echo " There were problems creating link!" + echo "Rotation not made!" + + echo -n "Remounting backup partition read-only ... " + if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." + else + echo "failure!" + echo " There were problems remounting $BACKUPPART in read-only mode!" + echo "### End of Backup Rotation ###" + exit 1 + fi + echo "### End of Backup Rotation ###" + exit 1 +fi + +echo -n "Remounting backup partition read-only ... " +if ( mount $BACKUPPART -o remount,ro &> /dev/null ) then + echo "done." +else + echo "failure!" + echo " There were problems remounting $BACKUPPART in read-only mode!" + echo "### End of Backup Rotation ###" + exit 1 +fi +echo "### End of Backup Rotation ###" diff --git a/examples/cron_dump_to_disk/backupskel.tar.gz b/examples/cron_dump_to_disk/backupskel.tar.gz new file mode 100644 index 0000000..68614a9 Binary files /dev/null and b/examples/cron_dump_to_disk/backupskel.tar.gz differ diff --git a/examples/cron_dump_to_disk/crontab_entries.txt b/examples/cron_dump_to_disk/crontab_entries.txt new file mode 100644 index 0000000..f7ca35e --- /dev/null +++ b/examples/cron_dump_to_disk/crontab_entries.txt @@ -0,0 +1,4 @@ +# Perform Nightly Backup (nightly incremental + weekly full + monthly full) +02 06 * * 1-6 root backup_rotate ; nice -1 backup inc +02 06 * * sun root backup_rotate ; nice -1 backup full +07 00 01 * * root backup_rotate monthly ; backup full nodumpdate diff --git a/examples/dump_on_cd/README b/examples/dump_on_cd/README new file mode 100644 index 0000000..ae04ce5 --- /dev/null +++ b/examples/dump_on_cd/README @@ -0,0 +1,53 @@ + Experimental dump to CDROMs + =========================== + +Starting with dump/restore version 0.4b24 or later versions of +dump/restore you can dump to CDROMs. + +You need a (successfully installed) CD-writing software like + cdrecord (tested with versions 1.11a04 onwards) + +These scripts use the new switch ('V') to restore +which signals a multi-volume (non-tape) medium like CDROMs + +I have used the shell scripts below to generate/verify the dump + +YOU MUST MODIFY these - especially + +- adapt FS to the filesystem to be dumped +- UserExit to the path to the user exit function like UserInfo below +- FiFo to the path to a named pipe (better not on the same filesystem) +- your cd device(s) ( I have /dev/cdrom a symlink to /dev/sr0 and + /dev/cdrw a symlink to /dev/sr1 ) +- your path to cdrecord and +- - cdrecord's dev parameter must be adapted to your CD burner +- - cdrecord's fs (= input fifo size), use less than 64m if you + are short of memory +- - cdrecord's speed parameter : this parameter not only depends on the + capabilities of your CD burner BUT also on the speed of your CPU !!! + With the dump -z6 compression on a 900 MHz Pentium III I had no problems + with speed=4 which is the maximum speed for my burner. + It looks as if at least speed=6 would be possible on a 900 MHz Pentium III. + If speed is to large, cdrecord's input fifo gets empty (as + shown by cdrecord) and then you have a buffer underrun. + +- replace the wayplay command with something which alerts you if you + have to change CDROMS + +- for restore or verification replace /dev/cdrom by something + which applies for you (device for the CDreader) + + +DON'T FORGET to generate a boot-CD which has the 0.4b24 restore + or a newer version of restore on board + +I prefer timos_Rescue_Cd_Set-0.6.1 see http://rescuecd.sourceforge.net + + +Please Cc bug-reports to jarausch@igpm.rwth-aachen.de + +----------------------------------------------------------------- +This file and the scripts were slightly edited when the +Helmut Jarausch patch was integrated in dump-0.4b24. + Stelian. + diff --git a/examples/dump_on_cd/dump_userinfo.sh b/examples/dump_on_cd/dump_userinfo.sh new file mode 100755 index 0000000..9096048 --- /dev/null +++ b/examples/dump_on_cd/dump_userinfo.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# $1 = filename +# $2 = sequence number + +wavplay -q /root/alert.wav +num=$[$2+1] +echo "insert next CD (number $num) " +read -p "CD number $num ready? " Ans + +xterm -hold -T cdrecord_$num -e \ + /usr/local/bin/cdrecord dev=0,1,0 fs=64m \ + -v speed=4 -eject -pad -data $1 & diff --git a/examples/dump_on_cd/start_dump.sh b/examples/dump_on_cd/start_dump.sh new file mode 100755 index 0000000..df98c0a --- /dev/null +++ b/examples/dump_on_cd/start_dump.sh @@ -0,0 +1,24 @@ +#!/bin/bash +if [ `id -u` != 0 ]; then + echo "root priviledges are required" + exit 1 +fi +Level=0 +Label=`date -I` +#CD_Cap=650 +CD_Cap=700 +eval Cap=$(($CD_Cap*1024)) +FS=/ +UserExit=/root/dump_userinfo.sh +FiFo=/tmp/dump.fifo +rm -f $FiFo +mkfifo $FiFo +xterm -T cdrecord_1 -hold -e cdrecord dev=0,1,0 fs=64m \ + -v speed=4 -eject -pad -data $FiFo & + +/sbin/dump -z6 -b64 -B$Cap -F $UserExit \ + -$Level -L $Label -f $FiFo $FS + +wavplay -q /root/alert.wav +rm -f $FiFo + diff --git a/examples/dump_on_cd/verify_dump.sh b/examples/dump_on_cd/verify_dump.sh new file mode 100755 index 0000000..2b19702 --- /dev/null +++ b/examples/dump_on_cd/verify_dump.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ `id -u` != 0 ]; then + echo "root priviledges are required" + exit 1 +fi +cd / +/sbin/restore -V -b64 -C -f /dev/cdrom diff --git a/examples/dump_on_cd_2/DE/backup_CD b/examples/dump_on_cd_2/DE/backup_CD new file mode 100644 index 0000000..06f7c97 --- /dev/null +++ b/examples/dump_on_cd_2/DE/backup_CD @@ -0,0 +1,37 @@ +#!/bin/bash +# This script dumps the specified Filesystem via dump on a CD/DVD +# CD_CAPACITY defines the capacity in MB per CD +# The script for the next volume is passed via the -F option of dump +# !!! do NOT forget to change CD_CAPACITY in $EXITSCRIPT !!! +COMPRESSION_LEVEL=2 +RECORD_BIN="/usr/bin/cdrecord dev=0,0,0 speed=10 fs=64M -v -dao -eject -pad " +EXITSCRIPT="/root/bin/cd_dump_userexit" +FILESYSTEM="/home" +LEVEL=0 +LABEL="`date -I`" +# !!! do NOT forget to change CD_CAPACITY in $EXITSCRIPT !!! +# CD_CAPACITY=650 +CD_CAPACITY=700 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +BSIZE="$(echo "$CD_CAPACITY*1024" | bc -l )" +FIFO="/tmp/dump.fifo" +DUMP_BIN="/usr/sbin/dump -z$COMPRESSION_LEVEL -b64 -B$BSIZE -F $EXITSCRIPT -$LEVEL -L $LABEL -f $FIFO $FILESYSTEM" + +rm -f $FIFO +mkfifo $FIFO +ANSWER="" +while [ "$ANSWER" != "j" ] ; do + read -p "Ist die CD No. 1 eingelegt? (j/n)" ANSWER + if [ "$ANSWER" == "j" ] ; then + $RECORD_BIN -tsize=$TSIZE -data $FIFO & + $DUMP_BIN + rm -f $FIFO + exit 0 + else + EXIT="" + read -p "Wollen Sie abbrechen? (j/n)" EXIT + if [ "$EXIT" == "j" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/DE/backup_DVD b/examples/dump_on_cd_2/DE/backup_DVD new file mode 100644 index 0000000..fbee957 --- /dev/null +++ b/examples/dump_on_cd_2/DE/backup_DVD @@ -0,0 +1,44 @@ +#!/bin/bash +# This script dumps the specified Filesystem via dump on a CD/DVD +# CD_CAPACITY defines the capacity in MB per CD +# The script for the next volume is passed via the -F option of dump +# At least for my DVD-Recorder (a PHILIPS DVR-A03) it is necessary +# to define the tracksize for the next track before the DVD is written. +# This is done via the -tsize option of cdrecord. Since tsize takes its +# arguments in Bytes, the shell cannot compute the value correctly +# anymore (value too high), so I use bc. + +# !!! If you plan to write DVD's with other sizes, please correct the +# CD_CAPACITY in the dump_userexit_DVD script, too !!! + +COMPRESSION_LEVEL=2 +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +EXITSCRIPT="/root/bin/dvd_dump_userexit" +FILESYSTEM="/home" +LEVEL=0 +LABEL="`date -I`" +CD_CAPACITY=4300 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +BSIZE="$(echo "$CD_CAPACITY*1024" | bc -l )" +FIFO="/tmp/dump.fifo" +DUMP_BIN="/usr/sbin/dump -z$COMPRESSION_LEVEL -b64 -B$BSIZE -F $EXITSCRIPT -$LEVEL -L $LABEL -f $FIFO $FILESYSTEM" + +rm -f $FIFO +mkfifo $FIFO +ANSWER="" +while [ "$ANSWER" != "j" ] ; do + read -p "Ist die DVD No. 1 eingelegt? (j/n)" ANSWER + if [ "$ANSWER" == "j" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -eject -dao -pad -tsize=$TSIZE -data $FIFO & + $DUMP_BIN + rm -f $FIFO + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Wollen Sie abbrechen? (j/n)" EXIT + if [ "$EXIT" == "j" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/DE/dump_userexit_CD b/examples/dump_on_cd_2/DE/dump_userexit_CD new file mode 100644 index 0000000..a8f8db8 --- /dev/null +++ b/examples/dump_on_cd_2/DE/dump_userexit_CD @@ -0,0 +1,24 @@ +#!/bin/bash +# supplied info from "dump -F": +# $1 = filename +# $2 = sequence number + +NUM=$(($2+1)) +RECORD_BIN="/usr/bin/cdrecord speed=10 dev=0,0,0 fs=64M " +# CD_CAPACITY=700 +# TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +echo -e "Bitte die naechste CD einlegen (No. $NUM)\n" +ANSWER="" +while [ "$ANSWER" != "j" ] ; do + read -p "Ist die CD bereit? (j/n)" ANSWER + if [ "$ANSWER" == "j" ] ; then + $RECORD_BIN -eject -pad -data $1 & + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Wollen Sie abbrechen? (j/n)" EXIT + if [ "$EXIT" == "j" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/DE/dump_userexit_DVD b/examples/dump_on_cd_2/DE/dump_userexit_DVD new file mode 100644 index 0000000..bdfe22a --- /dev/null +++ b/examples/dump_on_cd_2/DE/dump_userexit_DVD @@ -0,0 +1,25 @@ +#!/bin/bash +# supplied info from "dump -F": +# $1 = filename +# $2 = sequence number + +NUM=$(($2+1)) +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +CD_CAPACITY=4300 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +echo "Bitte die naechste DVD einlegen (No. $NUM)" +ANSWER="" +while [ "$ANSWER" != "j" ] ; do + read -p "Ist die DVD bereit? (j/n)" ANSWER + if [ "$ANSWER" == "j" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -dao -eject -pad -tsize=$TSIZE -data $1 & + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Wollen Sie abbrechen? (j/n)" EXIT + if [ "$EXIT" == "j" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/EN/backup_CD b/examples/dump_on_cd_2/EN/backup_CD new file mode 100644 index 0000000..94ae81d --- /dev/null +++ b/examples/dump_on_cd_2/EN/backup_CD @@ -0,0 +1,36 @@ +#!/bin/bash +# This script dumps the specified Filesystem via dump on a CD/DVD +# CD_CAPACITY defines the capacity in MB per CD +# The script for the next volume is passed via the -F option of dump +# FILESYSTEM defines the filesystem to back up +COMPRESSION_LEVEL=2 +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +EXITSCRIPT="/root/bin/dvd_dump_userexit" +FILESYSTEM="/home" +LEVEL=0 +LABEL="`date -I`" +CD_CAPACITY=700 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +BSIZE="$(echo "$CD_CAPACITY*1024" | bc -l )" +FIFO="/tmp/dump.fifo" +DUMP_BIN="/usr/sbin/dump -z$COMPRESSION_LEVEL -b64 -B$BSIZE -F $EXITSCRIPT -$LEVEL -L $LABEL -f $FIFO $FILESYSTEM" + +rm -f $FIFO +mkfifo $FIFO +ANSWER="" +while [ "$ANSWER" != "y" ] ; do + read -p "Did you insert CD No. 1? (y/n)" ANSWER + if [ "$ANSWER" == "y" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -eject -pad -tsize=$TSIZE -data $FIFO & + $DUMP_BIN + rm -f $FIFO + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Do you really want to exit? (y/n)" EXIT + if [ "$EXIT" == "y" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/EN/backup_DVD b/examples/dump_on_cd_2/EN/backup_DVD new file mode 100644 index 0000000..518e95b --- /dev/null +++ b/examples/dump_on_cd_2/EN/backup_DVD @@ -0,0 +1,44 @@ +#!/bin/bash +# This script dumps the specified Filesystem via dump on a CD/DVD +# CD_CAPACITY defines the capacity in MB per CD +# The script for the next volume is passed via the -F option of dump +# At least for my DVD-Recorder (a PHILIPS DVR-A03) it is necessary +# to define the tracksize for the next track before the DVD is written. +# This is done via the -tsize option of cdrecord. Since tsize takes its +# arguments in Bytes, the shell cannot compute the value correctly +# anymore (value too high), so I use bc. + +# !!! If you plan to write DVD's with other sizes, please correct the +# CD_CAPACITY in the dump_userexit_DVD script, too !!! + +COMPRESSION_LEVEL=2 +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +EXITSCRIPT="/root/bin/dvd_dump_userexit" +FILESYSTEM="/home" +LEVEL=0 +LABEL="`date -I`" +CD_CAPACITY=4300 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +BSIZE="$(echo "$CD_CAPACITY*1024" | bc -l )" +FIFO="/tmp/dump.fifo" +DUMP_BIN="/usr/sbin/dump -z$COMPRESSION_LEVEL -b64 -B$BSIZE -F $EXITSCRIPT -$LEVEL -L $LABEL -f $FIFO $FILESYSTEM" + +rm -f $FIFO +mkfifo $FIFO +ANSWER="" +while [ "$ANSWER" != "y" ] ; do + read -p "Did you insert DVD No. 1? (y/n)" ANSWER + if [ "$ANSWER" == "y" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -eject -dao -pad -tsize=$TSIZE -data $FIFO & + $DUMP_BIN + rm -f $FIFO + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Do you really want to exit? (y/n)" EXIT + if [ "$EXIT" == "y" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/EN/dump_userexit_CD b/examples/dump_on_cd_2/EN/dump_userexit_CD new file mode 100644 index 0000000..cb45989 --- /dev/null +++ b/examples/dump_on_cd_2/EN/dump_userexit_CD @@ -0,0 +1,23 @@ +#!/bin/bash +# supplied info from "dump -F": +# $1 = filename +# $2 = sequence number + +NUM=$(($2+1)) +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +echo "Please insert the next CD (No. $NUM)" +ANSWER="" +while [ "$ANSWER" != "y" ] ; do + read -p "Is the CD ready? (y/n)" ANSWER + if [ "$ANSWER" == "y" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -eject -pad -data $1 & + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Do you really want to exit? (y/n)" EXIT + if [ "$EXIT" == "y" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/EN/dump_userexit_DVD b/examples/dump_on_cd_2/EN/dump_userexit_DVD new file mode 100644 index 0000000..e5fcef4 --- /dev/null +++ b/examples/dump_on_cd_2/EN/dump_userexit_DVD @@ -0,0 +1,25 @@ +#!/bin/bash +# supplied info from "dump -F": +# $1 = filename +# $2 = sequence number + +NUM=$(($2+1)) +RECORD_BIN="/usr/bin/dvdrecord dev=0,0,0 fs=64M speed=2 " +CD_CAPACITY=4300 +TSIZE="$(echo "$CD_CAPACITY*1024*1024" | bc -l )" +echo "Please insert the next DVD (No. $NUM)" +ANSWER="" +while [ "$ANSWER" != "y" ] ; do + read -p "Is the DVD ready? (y/n)" ANSWER + if [ "$ANSWER" == "y" ] ; then + $RECORD_BIN -blank=fast + $RECORD_BIN -dao -eject -pad -tsize=$TSIZE -data $1 & + exit 0 + elif [ "$ANSWER" == "n" ] ; then + EXIT="" + read -p "Do you really want to exit? (y/n)" EXIT + if [ "$EXIT" == "y" ] ; then + exit 1 + fi + fi +done diff --git a/examples/dump_on_cd_2/README b/examples/dump_on_cd_2/README new file mode 100644 index 0000000..d4ed661 --- /dev/null +++ b/examples/dump_on_cd_2/README @@ -0,0 +1,12 @@ +[...] +Since I modified the dump_on_cd scripts [...by adding the +possibility to dump to DVD media...] and thereby +translated them to german, I attached them here. + +Furthermore, I think I improved the useability a bit. + +I hope you find them useful, + +Yours, + +Georg Lippold diff --git a/examples/dump_on_remote_cd/README b/examples/dump_on_remote_cd/README new file mode 100644 index 0000000..d07761d --- /dev/null +++ b/examples/dump_on_remote_cd/README @@ -0,0 +1,35 @@ +> I'll be more than happy to put a copy of your scripts in the dump +> distribution once you'll get this work :-) + +So you may have a look at the enclosed scripts. + +I use rsh in both directions. This may easily be changed to ssh. + +Basically three scripts are now necessary. The first wraps around the +dump-command, the second acts as user exit when CD has to be changed +and the third has to be run on the remote box. + +To make things easier I put the first two into one file called +dump-to-remote-cd. The second file called get-dumpdata-to-cdrecord must +be copied to the box with the CD-Burner. There is a small +configuration section in it to get cdrecord to work. + +dump-to-remote-cd may be called with the capacity of the media which +is used and / or a filesystem argument passed to dump. + +Usage is: + +dump-to-remote-cd [ -c ] [files to dump ...] + +There are defaults in the scripts which are used if any of these +arguments are missing. The hostname of the box with the CD-burner +has to be edited in any case. + +Kind regards + +Gerd + +------------------------------------------------------------------------ +Gerd Bavendiek Linux Laptop Users check out: +bav@epost.de http://netenv.sourceforge.net +------------------------------------------------------------------------ diff --git a/examples/dump_on_remote_cd/dump-to-remote-cd b/examples/dump_on_remote_cd/dump-to-remote-cd new file mode 100755 index 0000000..cefc321 --- /dev/null +++ b/examples/dump_on_remote_cd/dump-to-remote-cd @@ -0,0 +1,98 @@ +#!/bin/bash +#ident "@(#) dump-to-remote-cd Time-stamp: <02/05/06 15:12:29 bav> " +#****************************************************************** +# dump-to-remote-cd +#****************************************************************** +# Gerd Bavendiek bav@epost.de 02-05-02 +# +# Script used to dump to a remote box with a CD-Burner. There is a +# companion script called get-dumpdata-to-cdrecord. +# +# Usage: dump-to-remote-cd [ -c ] [files to dump ...] +# +# If called without arguments, it will dump / assuming 650 MB Media on +# host kiki (see DEFAULT_ below). +# +# You must be able to do an rsh as root to BURN_HOST and vice versa, +# see get-dumpdata-to-cdrecord. You may use ssh instead. +#------------------------------------------------------------------ + +#--- Customize to fit your needs ---------------------------------- + +PATH_TO_GET_DUMPDATA_TO_CDRECORD=/root/tools/get-dumpdata-to-cdrecord +PATH_TO_XTERM=/usr/X11R6/bin/xterm + +FIFO_NAME=/tmp/get-dumpdata-to-cdrecord.fifo + +BURN_HOST=kiki + +DEFAULT_CD_CAPACITY=650 +DEFAULT_FS=/ + +#--- End of customizing ------------------------------------------- + +USER_EXIT=$0 + +Usage(){ +echo >&2 "Usage: `basename $0` [ -c ] [files to dump ...]" + exit 1 +} + +if [ `id -u` != 0 ]; then + echo "$0: ERROR: root priviledges are required ..." + exit 1 +fi + +# Check whether first argument is a named pipe +if [ -p "$1" ]; then + # We are called internally either from ourselves or from dump + FIFO_NAME=$1 + num=$[$2+1] + tput bel;sleep 1; tput bel + echo "Insert next CD (number $num) ..." + read -p "CD number $num ready ? " Ans + DUMP_HOST=`uname -n` + rsh $BURN_HOST \ + $PATH_TO_XTERM -hold -T "Dump_CD_number_$num" -cr red -fn 6x10 -e \ + $PATH_TO_GET_DUMPDATA_TO_CDRECORD -d $DUMP_HOST -f $FIFO_NAME & + exit 0 +fi + +CD_CAPACITY=$DEFAULT_CD_CAPACITY +FS=$DEFAULT_FS + +# We will reach this code only when not called internally +while getopts "b:c:h" c; do + case $c in + c) # Media Capacity + CD_CAPACITY=$OPTARG + ;; + h) # help those who ask for help + Usage + ;; + '?') # any other switch + Usage + ;; + esac +done + +shift `expr $OPTIND - 1` + +if [ -n "$*" ]; then FS="$*"; fi + +DumpLevel=0 # level 0 dump +Label=`date -I` # Take today's date as label, e.g. 2002-05-02 + +eval Capacity=$(($CD_CAPACITY*1024)) + +# Remove the fifo on the server and make a new one +rm -f $FIFO_NAME; mkfifo $FIFO_NAME + +# Call user exit for the very first time, all further calls will be +# done via dump +$USER_EXIT $FIFO_NAME 0 +sleep 2 + +# Run dump +dump -z -B$Capacity -F $USER_EXIT -$DumpLevel -L $Label -f $FIFO_NAME $FS + diff --git a/examples/dump_on_remote_cd/get-dumpdata-to-cdrecord b/examples/dump_on_remote_cd/get-dumpdata-to-cdrecord new file mode 100755 index 0000000..ef7f226 --- /dev/null +++ b/examples/dump_on_remote_cd/get-dumpdata-to-cdrecord @@ -0,0 +1,60 @@ +#!/bin/bash +#ident "@(#) get-dumpdata-to-cdrecord Time-stamp: <02/05/06 13:49:28 bav> " +#****************************************************************** +# get-dumpdata-to-cdrecord +#****************************************************************** +# Gerd Bavendiek bav@epost.de 02-05-02 +# +# This script runs on the box which has the CD-Burner. It starts an +# rsh on the box where dump is started and feeds the data to +# cdrecord. You should have copied it to +# PATH_TO_GET_DUMPDATA_TO_CDRECORD, see script dump-to-remote-cd. +# +# You definitely may wish to customize the cdrecords arguments below ! +# +# If rsh is not appropiate for you, change to ssh. +#------------------------------------------------------------------ + +CDRECORD_TESTMODE="" # This means: burn ! +###CDRECORD_TESTMODE="-dummy" # and this: not really ... +CDRECORD_DEVICE="1,0" # Run cdrecord --scanbus if in doubt +CDRECORD_SPEED=2 # Speed of your burner +CDRECORD_BUFFERSIZE=16m # Buffersize in MByte + +#------------------------------------------------------------------ +Usage() +{ + echo >&2 "Usage: `basename $0` -d -f " + exit 1 +} + +CDRECORD_ARGLIST="-v $CDRECORD_TESTMODE dev=$CDRECORD_DEVICE speed=$CDRECORD_SPEED fs=$CDRECORD_BUFFERSIZE" + +while getopts "d:f:h" c; do + case $c in + d) # the dump host + DUMP_HOST=$OPTARG + ;; + f) # name of the fifo cdrecord has to read the data from + FIFO_NAME=$OPTARG + ;; + h) # help those who ask for help + Usage + ;; + '?') # any other switch + Usage + ;; + esac +done + +if [ -z "$DUMP_HOST" -o -z "$FIFO_NAME" ]; then Usage; fi + +rsh $DUMP_HOST dd if=$FIFO_NAME | cdrecord $CDRECORD_ARGLIST -eject -pad -data - +if [ $? -ne 0 ]; then + echo $0: `date '+%T'`: ERROR: Check cdrecords messages + exit 1 +fi + +# Local Variables: +# rcpbuf-todo: ("/[root@kiki]/root/tools") +# End: diff --git a/examples/encrypted_rmt/README b/examples/encrypted_rmt/README new file mode 100644 index 0000000..12a95f5 --- /dev/null +++ b/examples/encrypted_rmt/README @@ -0,0 +1,77 @@ +This is a set of changes to the Linux "rmt" utility +to support transparent encryption. +Data is encrypted before it is written to tape, and decrypted when read. +We use no padding or salt, so the data size doesn't change. +Tools that use rmt for remote tape access (such as dump, restore +and tar) can manipulate encrypted data without modification. + +The symmetric cipher is currently hardwired as Blowfish. + +[...] + +Building ermt: +- Ensure that openssl-0.9.7a or later is installed. +- Configure and build the package, enabling ermt support: + ./configure --enable-ermt + make + This will build an extra binary: rmt/ermt, the encrypting version. + If ermt fails to link because EVP_CIPHER_CTX_set_padding + is undefined, you must upgrade to openssl-0.9.7a or later. + +Run-time setup: +- Create a user for remote tape access, which we will call "dump": + useradd -m dump +- ermt reads the secret key from ".ermt.key". + Generate a random key in ~dump/.ermt.key: + su - dump + openssl rand -out .ermt.key 32 + chmod 400 .ermt.key + Due to the way "openssl enc -kfile $file" reads the key file, + you should ensure that the key contains no \0 or \r or \n characters, + which would prematurely truncate the key length. +- Protect the key: copy to many floppies, "od -x .ermt.key|lpr", etc. +- Set up rsh access from root (or whoever you run dump as) + to dump@localhost: + # still running as user dump here + echo localhost root > .rhosts + chmod 400 .rhosts + Or use ssh if you prefer; details left as an exercise. +- Check that it works: run "rsh localhost -l dump date" as root. +- Copy the ermt binary you built above to ~dump, + and change dump's shell to ~dump/ermt. + +Backup usage: just dump remotely to localhost: + + dump -0u -f dump@localhost:/dev/st0 / + restore -i -f dump@localhost:/dev/st0 + # You can use GNU tar too + +If your device is doing hardware compression, it's best to turn +it off, since encrypted data compresses very poorly. + +Emergency decrypting: if you need to restore a tape and +don't have access to a host running ermt, +you have two choices: +- If you have a copy of the ermt binary, run it with the -d switch + to decrypt stdin to stdout: + dd if=/dev/st0 bs=10k | + (cd ~dump; ./ermt -d) | # assuming ermt is in ~dump + restore -i -f - +- If not, use the OpenSSL "openssl" command, which does the same thing: + dd if=/dev/st0 bs=10k | + openssl enc -d -kfile ~dump/.ermt.key -blowfish -nosalt -nopad | + restore -i -f - + Versions of OpenSSL before 0.9.7a don't understand -nopad, + so they won't work. + +How much does encryption slow down backups? +In my tests, the network hop is the bottleneck: +dumping unencrypted (i.e. standard rmt) to localhost is 38% +slower than dumping directly to tape. +Adding encryption makes no difference, which isn't surprising. + +Change log: + 2003-04-08: added configure --enable-ermt, separate ermt binary + 2003-04-06: Initial release + +-- Ken Lalonde diff --git a/examples/howto/ultra-mini-howto b/examples/howto/ultra-mini-howto new file mode 100644 index 0000000..a3628e5 --- /dev/null +++ b/examples/howto/ultra-mini-howto @@ -0,0 +1,314 @@ +Dump/Restore Ultra-Mini-FAQ + +Document v1.1 + +Disclaimer: I am not an expert in dump/restore. In +fact, I'm a newbie. But I've been picking things up as +I implement it here and I wanted to pass some of those +things along in the form of a very basic FAQ. + +-Patrick Walsh + +1) Introduction/ Non-rewinding device +2) Dump command line +3) Sending 2 or more filesystems to a tape +4) Compressing dumps on the fly +5) The "nodump" file and directory attribute. +6) Restoring your dumps (including compressed). +7) How to confirm a backup (highly recommended) +8) What are the best buffer size options? +9) Experiencing bread, lseek, lseek2 errors. +10) Example backup script + + 1) Introduction/ Non-rewinding device + +You use dump to backup to a file or a tape device. If +you're backing up to a tape device, then the first +thing you need to understand is that there are two +devices that refer to your tape drive. There is the +"rewinding" device and the "non-rewinding" device. + +I wish I could tell you an easy way to figure out what +your device names are, but I don't know one. On my +local box I had a /dev/tape device that linked to +/dev/st0. It turns out that /dev/st0 is my "rewinding" +tape drive. If I write to this device it will always +rewind before starting to write. This means that if +you try to dump two filesystems, only the second one +will be stored. If your tape device is /dev/st0, like +mine, then your non-rewinding tape device is probably +/dev/nst0. + +Anyway, through the rest of this I will refer to $TAPE +and $RWTAPE. $TAPE is the non-rewinding device (in my +case /dev/nst0) and $RWTAPE is the rewinding tape (in +my case /dev/st0 and /dev/tape). $FS is the filesystem +you are backing up, such as /dev/hda1. + + 2) What options should I use? + +Use the man page to figure out what options to send +to dump. I use "dump 0uanf $TAPE $FS". + + u=update /etc/dumpdates after a successful dump + a=auto-size -- bypass all tape length calculations + and write until eof + n=notify 'operators' group when dump needs attention + f=backup to file or device specified, or - for stdout + + 3) You want to send two or more filesystems to tape. + +OK, rewind using the mt command, then dump multiple +times to the non-rewinding device, and you're done: + +mt -f $TAPE rewind +dump 0uanf $TAPE $FS1 +dump 0uanf $TAPE $FS2 +etc. + +Check the man page of mt if you want to know how to +eject the tape or retension it or anything. + + 4) You want to compress your dumps on the fly. No +problem. Send your backup to STDOUT and manipulate it +from there. It's easier if you're sending your output +to the hard drive: + +dump 0uanf - $FS | gzip -c > /backup/outfile.dump.gz + +You want that to be written to the tape on the fly? +Try this: + +mt -f $TAPE rewind +dump 0uanf - $FS |gzip -c |dd if=- of=$TAPE + +[ You can also use the -z or -J options of dump in the + recent versions to enable internal compression - stelian ] + + 5) You read the man page and you're wondering what the +heck a "nodump" flag is. For example, how can you get +dump to stop backing up /tmp or ~/.netscape/cache. You +have two options: either exclude the inode in your dump +command, or flag the files and directories with the +"nodump" flag. To flag /tmp, for example, do this: + +chattr -R +d /tmp + +Want more details? Try 'man chattr' and 'man lsattr'. + + 6) You want to know how to restore your backup. + +Read the restore man page. But barring that, the easy +way is to use restore in interactive mode. If you have +three filesystems on one tape and you want to restore +files from the second one, you need to do this: + +mt -f $TAPE rewind +mt -f $TAPE fsf 1 # skip forward one file +restore -if $TAPE + +OK, suppose now that you used the commands in section 4 +to compress the dump file before it was written to +disk. Use this command: + +mt -f $TAPE rewind +mt -f $TAPE fsf 1 +dd if=$TAPE of=- |gzip -dc |restore -rf - + +Obviously if you dumped to a file instead of a tape it +is much easier: + +gzip -dc $filename |restore -rf - + + 7) How to confirm your backup + + Check out the restore man page and read up on the -C +option. + + 8) What are the best buffer size options? + + Bernhard R. Erdmann answered this question on the +dump-users mailing list. His excellent response +follows: + +>> While I was doing google searches, there seems to be +>> an issue regarding the default buffer size writing +>> to tape. According to some, the default buffer size +>> of 512 can harm modern drives. I have a Seagate +>> DDS3 unit and am wondering what the best mt/dump +>> options are. I am using datacompression in +>> hardware. Should I go with a large buffer (mt +>> setblk 10240) or variable (mt setblk 0). If I +>> change these sizes, does dump need to know about it? +> +>Dump/restore uses a default blocksize of 10 KB. You +>can change it with the "-b" option or use dd for +>(re-)blocking. +> +>dump 0ab 32 / +>dump 0af - / | dd obs=32k of=$TAPE +>ssh host "/sbin/dump 0af - /" | dd obs=32k of=$TAPE +>restore rb 32 +>dd ibs=32k if=$TAPE | restore rf - +>ssh host "dd if=/dev/nst0 ibs=32k" | restore rf - +> +>Personally, I'd stick with variable blocksize on the +>drive and use 32 KB as the application's blocksize as +>Amanda uses that size, too. +> +>Rumours told using 64 KB or 128 KB blocksize yields to +>increase performance (maybe on the mtx list from an +>Arkeia developer) didn't had any effects in my own +>tests with blocksizes ranging from 10 to 64 KB some +>months ago on a DDS-2 drive. +> +>Regarding tape drive performance at different block +>sizes you may want to read +>http://www.rs6000.ibm.com/support/micro/tapewhdr.html#Header_133 +> +>- Block size, can effect the time for backup/restore. +>Using large blocksizes may improve performance. Using +>small block sizes can increase system overhead but +>before changing to a large blocksize it is necessary +>to be sure the user application supports the larger +>blocksize chosen. +>- Very long restore times due to blocksize. If a +>backup is done with a fixed block length then the +>restore should be done with the same fixed block +>length. If a backup is done with a fixed block length +>and the restore is done with variable block length, +>the restore may work successfully but it may take many +>more hours to restore than it took to back up the +>data. The reason for this is that when AIX reads fixed +>block length data in variable block mode, a check +>condition is issued by the tape drive on every read. +>AIX must interpret every check condition and determine +>the proper action to take. This often will put the +>tape drive into a mode of reading that will require +>the tape drive to stop tape motion, rewind the tape +>some distance, then start reading again. This will +>reduce the life expectancy of the tape and increase +>the time it takes to backup data. + + 9) Experiencing bread, lseek, and lseek2 errors. + + These errors are caused by inodes being changed +during the backup. This is normal because dump and +the Linux kernel are both acessing the filesystem +and there is no consistence checking. By "calming" +the system (killing unnecessary processes), you +decrease the likelihood of having these +errors. Read up on the bug on Sourcefourge: + +http://sourceforge.net/tracker/index.php?func=detail&aid=204909&group_id=1306&atid=101306 + +Note that the only "real" solution to this problem +is to dump a unmounted filesystem or use a filesystem +snapshot feature (like in LVM). + + 10) That about sums up my knowledge on the matter, but +I feel better having written something for other peopleto look at so it doesn't take them quite so long to +learn the things I did. I've included my backup script +below. There are much better ones floating around, so +go find someone else's and use theirs if mine won't +work for you or you don't understand it. + + +#!/bin/csh +# System backup script for NARNIA + +# This is a script that will backup the entire hard drive +# to the NT server (not my choice) \\fs1. +# +# On each Sunday night, a full backup will be made +# of the hard drive and each day of the week thereafter an incremental +# backup will be made that captures only those changes since the night +# before. +# Each full backup will be sent to the local tape as well as to the +# NT machine. +# +# The files will be stored in partition-specific files with integer +# endings that specify the day of the week they were saved. Files +# with zero on the end will always be full backups. + +# Dump options: +# a=auto-size -- bypass all tape length calculations and write until eof +# f=write the backup to file or device specified or - for stdout +# n=notify operators group when dump needs attention +# u=update /etc/dumpdates after a successful dump + +# Set variables that control the script. +setenv MOUNTPOINT '/root/fs1backup' +setenv OUTDIR '/root/fs1backup/narnia' +setenv TAPE '/dev/nst0' # non-rewinding tape + +# Auto-set variable that determines level of backup. +setenv DAY `date +'%w'` + +# Mount the backup partition to /root/fs1backup +/usr/bin/smbmount \\\\fs1\\backup $MOUNTPOINT -o +"username=uname,password=pword" + +# Delete files created on this day last week +rm -f $OUTDIR/*$DAY.dump.gz + +# Do the actual backing up, one filesystem at a time. + +# /dev/hda1 = /boot +/sbin/dump $DAY'uanf' - /dev/hda1 | gzip -c >$OUTDIR/boot-$DAY.dump.gz + +# /dev/hda2 = / +/sbin/dump $DAY'uanf' - /dev/hda2 | gzip -c >$OUTDIR/root-$DAY.dump.gz + +# /dev/hda3 = /usr +/sbin/dump $DAY'uanf' - /dev/hda3 | gzip -c >$OUTDIR/usr-$DAY.dump.gz + +# /dev/hdb2 = /u1 +/sbin/dump $DAY'uanf' - /dev/hdb2 | gzip -c >$OUTDIR/u1-$DAY.dump.gz + + +# OK, presumably everything is now backed up to \\fs1. On level 0 +# dumps, lets backup to the local drive too. +if ($DAY == 0) then + mt -f $TAPE retension + foreach i ($OUTDIR/*0.dump.gz) + dd if=$i of=$TAPE + end + mt -f $TAPE rewind +endif + + +# Unmount the backup partition, not needed outside of script +umount /root/fs1backup + +# Explicitly free up the temporary variables +unsetenv DAY +unsetenv MOUNTPOINT +unsetenv OUTDIR +unsetenv TAPE + + +# RESTORE DIRECTIONS: +# If from tape: +# dd if=$TAPE of=- | gzip -dc | restore -rf - +# or dd if=$TAPE |gzip -dc |restore -rf - +# +# Note: must queue tape to proper position first. This +# is done by first rewinding then advancing to the proper +# file. The order that files are written to tape is +# *probably* 0=/boot 1=/ 2=/usr 3=/u1 +# +# Use mt to skip between them: +# mt -f $TAPE rewind +# restore -if $TAPE #now restoring /boot, probably +# mt -f $TAPE fsf 1 +# restore -if $TAPE #now restoring / +# mt -f $TAPE fsf 1 +# restore -if $TAPE #now restoring /usr +# #etc. +# +# Otherwise: +# gzip -dc $filename | restore -rf - + + + diff --git a/examples/remote_backup_ssh/backitup b/examples/remote_backup_ssh/backitup new file mode 100644 index 0000000..eacdd3b --- /dev/null +++ b/examples/remote_backup_ssh/backitup @@ -0,0 +1,59 @@ +#!/bin/sh + +# +# This script will backup local drives to a remote tape drive over ssh. +# written by David B. Peterson +# +# Follow these steps before using it the first time: +# 1. Configure the env variables below, especially OPERATOR, TAPEHOST +# TAPEDEV, and FILESYSTEMS +# 2. run the following commands as root (on the machine to be backed up): +# ssh-keygen -t dsa +# cat ~/.ssh/id_dsa.pub | ssh OPERATOR@TAPEHOST 'cat - >> ~/.ssh/authorized_keys2' +# +# where OPERATOR and TAPEHOST are as you have defined below. + +# We will run under screen so you can come back to the backup, if you need to. +if [ ! "$WINDOW" ]; then + exec screen $0 + exit +fi + +# ssh-agent allows us to backup securely without entering the passphrase so +# many times. This version uses openssh v2.9 +if [ ! $SSH_AGENT_PID ]; then + echo Starting ssh-agent... + exec ssh-agent -- /bin/sh $0 + exit +fi + +OPERATOR=backup +TAPEHOST=tapehost.example.com +TAPEDEV=/dev/nst0 +RMT=/sbin/rmt +RSH='/usr/bin/ssh' +DATE=`date +%Y%m%d` +DUMP='/sbin/dump 0auf' +LOGDIR=/var/log/backup +FILESYSTEMS='hda1 hda7 hda6 hda5 hda10' + +#### config above #### +# backup FILESYSTEMS to the TAPEDEV on TAPEHOST with DUMP as OPERATOR using RSH + +export RMT RSH +mkdir -p $LOGDIR &> /dev/null +ssh-add ~/.ssh/id_dsa + +echo "Rewinding tape..." +REWIND="mt -f $TAPEDEV rewind" +$RSH $OPERATOR@$TAPEHOST $REWIND + +for FS in $FILESYSTEMS +do + $DUMP $OPERATOR@$TAPEHOST:$TAPEDEV /dev/$FS 2>&1 | tee $LOGDIR/$FS.$DATE +done + +echo "Rewinding and ejecting tape..." +OFFLINE="mt -f $TAPEDEV offline" +$RSH $OPERATOR@$TAPEHOST $OFFLINE + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..11870f1 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f "$src" ] || [ -d "$src" ] + then + : + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + : + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + : + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/linux-1.2.x.patch b/linux-1.2.x.patch new file mode 100644 index 0000000..a313a0c --- /dev/null +++ b/linux-1.2.x.patch @@ -0,0 +1,17 @@ +--- fs/read_write.c.orig Sun Aug 27 15:41:29 1995 ++++ fs/read_write.c Sun Aug 27 15:42:39 1995 +@@ -112,9 +112,11 @@ + } + if (tmp < 0) + return -EINVAL; +- file->f_pos = tmp; +- file->f_reada = 0; +- file->f_version = ++event; ++ if (tmp != file->f_pos) { ++ file->f_pos = tmp; ++ file->f_reada = 0; ++ file->f_version = ++event; ++ } + memcpy_tofs(result, &file->f_pos, sizeof(loff_t)); + return 0; + } diff --git a/restore/Makefile.in b/restore/Makefile.in new file mode 100644 index 0000000..cdc2004 --- /dev/null +++ b/restore/Makefile.in @@ -0,0 +1,55 @@ +# $Id: Makefile.in,v 1.12 2003/05/08 21:11:39 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= .. + +@MCONFIG@ + +INC= -I$(top_srcdir)/restore +ALL_CFLAGS= @CPPFLAGS@ @CFLAGS@ @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) @RESTOREDEBUG@ +ALL_LDFLAGS= @LDFLAGS@ @LDOPTS@ @STATIC@ +LIBS= $(GLIBS) -le2p @READLINE@ @ZLIB@ @BZLIB@ +DEPLIBS= ../compat/lib/libcompat.a + +PROG= restore +RPROG= rrestore +LINKS= ${SBINDIR}/restore ${SBINDIR}/rrestore +SRCS= dirs.c interactive.c main.c restore.c symtab.c tape.c \ + utilities.c +OBJS= dirs.o interactive.o main.o restore.o symtab.o tape.o \ + utilities.o ../common/dumprmt.o +MAN8= restore.8 +RMAN8= rrestore.8 + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +all:: $(PROG) $(MAN8) + +$(PROG): $(OBJS) $(DEPLIBS) + $(CC) $(ALL_LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +$(MAN8): restore.8.in + sed -e "s|__DATE__|$(DATE)|g" \ + -e "s|__VERSION__|$(VERSION)|g" $< > $@ + +install:: all + $(INSTALL) -d $(SBINDIR) $(MANDIR) + $(INSTALLBIN) $(PROG) $(SBINDIR) + $(INSTALLMAN) $(MAN8) $(MANDIR) + cd $(SBINDIR) && $(RM) -f $(RPROG) && $(LN_S) $(PROG) $(RPROG) + cd $(MANDIR) && $(RM) -f $(RMAN8) && $(LN_S) $(MAN8) $(RMAN8) + +clean:: + $(RM) -f $(PROG) $(MAN8) \#* *.s *.o *.a *~ core + +distclean:: clean + $(RM) -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/restore/dirs.c b/restore/dirs.c new file mode 100644 index 0000000..2a23f94 --- /dev/null +++ b/restore/dirs.c @@ -0,0 +1,817 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: dirs.c,v 1.28 2004/05/25 10:39:30 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#else +#include +#include +#endif +#endif /* __linux__ */ +#include + +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#else +#ifdef sunos +#include +#else +#include +#endif +#endif + +#include "pathnames.h" +#include "restore.h" +#include "extern.h" + +/* + * Symbol table of directories read from tape. + */ +#define HASHSIZE 1000 +#define INOHASH(val) (val % HASHSIZE) +struct inotab { + struct inotab *t_next; + dump_ino_t t_ino; + OFF_T t_seekpt; + OFF_T t_size; +}; +static struct inotab *inotab[HASHSIZE]; + +/* + * Information retained about directories. + */ +struct modeinfo { + dump_ino_t ino; + struct timeval timep[2]; + mode_t mode; + uid_t uid; + gid_t gid; + unsigned int flags; +}; + +/* + * Definitions for library routines operating on directories. + */ +#undef DIRBLKSIZ +#define DIRBLKSIZ 1024 +struct rstdirdesc { + int dd_fd; + int32_t dd_loc; + int32_t dd_size; + char dd_buf[DIRBLKSIZ]; +}; + +/* + * Global variables for this file. + */ +static OFF_T seekpt; +static FILE *df, *mf; +static RST_DIR *dirp; +static char dirfile[MAXPATHLEN] = "#"; /* No file */ +static char modefile[MAXPATHLEN] = "#"; /* No file */ +static char dot[2] = "."; /* So it can be modified */ + +/* + * Format of old style directories. + */ +#define ODIRSIZ 14 +struct odirect { + u_short d_ino; + char d_name[ODIRSIZ]; +}; + +#if defined(__linux__) || defined(sunos) +static struct inotab *allocinotab __P((dump_ino_t, struct new_bsd_inode *, OFF_T)); +#else +static struct inotab *allocinotab __P((dump_ino_t, struct dinode *, OFF_T)); +#endif +static void dcvt __P((struct odirect *, struct direct *)); +static void flushent __P((void)); +static struct inotab *inotablookup __P((dump_ino_t)); +static RST_DIR *opendirfile __P((const char *)); +static void putdir __P((char *, size_t)); +static void putent __P((struct direct *)); +static void rst_seekdir __P((RST_DIR *, OFF_T, OFF_T)); +static OFF_T rst_telldir __P((RST_DIR *)); +static struct direct *searchdir __P((dump_ino_t, char *)); + +#ifdef sunos +extern int fdsmtc; +#endif + +/* + * Extract directory contents, building up a directory structure + * on disk for extraction by name. + * If genmode is requested, save mode, owner, and times for all + * directories on the tape. + */ +void +extractdirs(int genmode) +{ + int i; +#if defined(__linux__) || defined(sunos) + struct new_bsd_inode *ip; +#else + struct dinode *ip; +#endif + struct inotab *itp; + struct direct nulldir; + int fd; + + Vprintf(stdout, "Extract directories from tape\n"); + (void) snprintf(dirfile, sizeof(dirfile), "%s/rstdir%ld", tmpdir, + (long)dumpdate); + if (command != 'r' && command != 'R') { + (void) strncat(dirfile, "-XXXXXX", + sizeof(dirfile) - strlen(dirfile)); + fd = MKSTEMP(dirfile); + } else + fd = OPEN(dirfile, O_RDWR|O_CREAT|O_EXCL, 0666); + if (fd == -1 || (df = fdopen(fd, "w")) == NULL) { + if (fd != -1) + close(fd); + err(1, "cannot create directory temporary %s", dirfile); + } + if (genmode != 0) { + (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%ld", tmpdir, (long)dumpdate); + if (command != 'r' && command != 'R') { + (void) strncat(modefile, "-XXXXXX", + sizeof(modefile) - strlen(modefile)); + fd = MKSTEMP(modefile); + } else + fd = OPEN(modefile, O_RDWR|O_CREAT|O_EXCL, 0666); + if (fd == -1 || (mf = fdopen(fd, "w")) == NULL) { + if (fd != -1) + close(fd); + err(1, "cannot create modefile %s", modefile); + } + } + nulldir.d_ino = 0; + nulldir.d_type = DT_DIR; + nulldir.d_namlen = 1; + nulldir.d_name[0] = '/'; + nulldir.d_name[1] = '\0'; + nulldir.d_reclen = DIRSIZ(0, &nulldir); + for (;;) { + curfile.name = ""; + curfile.action = USING; + ip = curfile.dip; + if (ip == NULL || (ip->di_mode & IFMT) != IFDIR) { + if ( fclose(df) == EOF ) + err(1, "cannot write to file %s", dirfile); + dirp = opendirfile(dirfile); + if (dirp == NULL) + warn("opendirfile"); + if (mf != NULL && fclose(mf) == EOF ) + err(1, "cannot write to file %s", dirfile); + i = dirlookup(dot); + if (i == 0) + panic("Root directory is not on tape\n"); + return; + } + itp = allocinotab(curfile.ino, ip, seekpt); + getfile(putdir, xtrnull); + putent(&nulldir); + flushent(); + itp->t_size = seekpt - itp->t_seekpt; + } +} + +/* + * skip over all the directories on the tape + */ +void +skipdirs(void) +{ + + while (curfile.dip && (curfile.dip->di_mode & IFMT) == IFDIR) { + skipfile(); + } +} + +/* + * Recursively find names and inumbers of all files in subtree + * pname and pass them off to be processed. + */ +void +treescan(char *pname, dump_ino_t ino, long (*todo) __P((char *, dump_ino_t, int))) +{ + struct inotab *itp; + struct direct *dp; + int namelen; + OFF_T bpt; + char locname[MAXPATHLEN + 1]; + + itp = inotablookup(ino); + if (itp == NULL) { + /* + * Pname is name of a simple file or an unchanged directory. + */ + (void) (*todo)(pname, ino, LEAF); + return; + } + /* + * Pname is a dumped directory name. + */ + if ((*todo)(pname, ino, NODE) == FAIL) + return; + /* + * begin search through the directory + * skipping over "." and ".." + */ + namelen = snprintf(locname, sizeof(locname), "%s/", pname); + if (namelen >= (int)sizeof(locname)) + namelen = sizeof(locname) - 1; + rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); + dp = rst_readdir(dirp); /* "." */ + if (dp != NULL && strcmp(dp->d_name, ".") == 0) + dp = rst_readdir(dirp); /* ".." */ + else + fprintf(stderr, "Warning: `.' missing from directory %s\n", + pname); + if (dp != NULL && strcmp(dp->d_name, "..") == 0) + dp = rst_readdir(dirp); /* first real entry */ + else + fprintf(stderr, "Warning: `..' missing from directory %s\n", + pname); + bpt = rst_telldir(dirp); + /* + * a zero inode signals end of directory + */ + while (dp != NULL) { + locname[namelen] = '\0'; + if (namelen + dp->d_namlen >= (int)sizeof(locname)) { + fprintf(stderr, "%s%s: name exceeds %ld char\n", + locname, dp->d_name, (long)sizeof(locname) - 1); + } else { + (void) strncat(locname, dp->d_name, (int)dp->d_namlen); + treescan(locname, dp->d_ino, todo); + rst_seekdir(dirp, bpt, itp->t_seekpt); + } + dp = rst_readdir(dirp); + bpt = rst_telldir(dirp); + } +} + +/* + * Lookup a pathname which is always assumed to start from the ROOTINO. + */ +struct direct * +pathsearch(const char *pathname) +{ + dump_ino_t ino; + struct direct *dp; + char *path, *name, buffer[MAXPATHLEN]; + + strcpy(buffer, pathname); + path = buffer; + ino = ROOTINO; + while (*path == '/') + path++; + dp = NULL; +#ifdef __linux__ + while ((name = strsep(&path, "/")) != NULL && *name /* != NULL */) { +#else + while ((name = strtok_r(NULL, "/", &path)) != NULL && *name /* != NULL */) { +#endif + if ((dp = searchdir(ino, name)) == NULL) + return (NULL); + ino = dp->d_ino; + } + return (dp); +} + +/* + * Lookup the requested name in directory inum. + * Return its inode number if found, zero if it does not exist. + */ +static struct direct * +searchdir(dump_ino_t inum, char *name) +{ + struct direct *dp; + struct inotab *itp; + int len; + + itp = inotablookup(inum); + if (itp == NULL) + return (NULL); + rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); + len = strlen(name); + do { + dp = rst_readdir(dirp); + if (dp == NULL) + return (NULL); + } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0); + return (dp); +} + +/* + * Put the directory entries in the directory file + */ +static void +putdir(char *buf, size_t size) +{ + struct direct cvtbuf; + struct odirect *odp; + struct odirect *eodp; + struct direct *dp; + long loc, i; + + if (cvtflag && !ufs2flag) { + eodp = (struct odirect *)&buf[size]; + for (odp = (struct odirect *)buf; odp < eodp; odp++) + if (odp->d_ino != 0) { + dcvt(odp, &cvtbuf); + putent(&cvtbuf); + } + } else { + for (loc = 0; loc < (long)size; ) { + dp = (struct direct *)(buf + loc); +#ifdef DIRDEBUG + printf ("reclen = %d, namlen = %d, type = %d\n", + dp->d_reclen, dp->d_namlen, dp->d_type); +#endif + if (Bcvt) + swabst((u_char *)"is", (u_char *) dp); + if (oldinofmt && dp->d_ino != 0) { +# if BYTE_ORDER == BIG_ENDIAN + if (Bcvt) + dp->d_namlen = dp->d_type; +# else + if (!Bcvt) + dp->d_namlen = dp->d_type; +# endif + if (dp->d_namlen == 0 && dp->d_type != 0) + dp->d_namlen = dp->d_type; + dp->d_type = DT_UNKNOWN; + } +#ifdef DIRDEBUG + printf ("reclen = %d, namlen = %d, type = %d\n", + dp->d_reclen, dp->d_namlen, dp->d_type); +#endif + i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); + if ((dp->d_reclen & 0x3) != 0 || + dp->d_reclen > i || + dp->d_reclen < DIRSIZ(0, dp) +#if MAXNAMLEN < 255 + || dp->d_namlen > MAXNAMLEN +#endif + ) { + Vprintf(stdout, "Mangled directory: "); + if ((dp->d_reclen & 0x3) != 0) + Vprintf(stdout, + "reclen not multiple of 4 "); + if (dp->d_reclen < DIRSIZ(0, dp)) + Vprintf(stdout, + "reclen less than DIRSIZ (%d < %d) ", + dp->d_reclen, DIRSIZ(0, dp)); +#if MAXNAMLEN < 255 + if (dp->d_namlen > MAXNAMLEN) + Vprintf(stdout, + "reclen name too big (%d > %d) ", + dp->d_namlen, MAXNAMLEN); +#endif + Vprintf(stdout, "\n"); + loc += i; + continue; + } + loc += dp->d_reclen; + if (dp->d_ino != 0) { + putent(dp); + } + } + } +} + +/* + * These variables are "local" to the following two functions. + */ +static char dirbuf[DIRBLKSIZ]; +static long dirloc = 0; +static long prev = 0; + +/* + * add a new directory entry to a file. + */ +static void +putent(struct direct *dp) +{ + dp->d_reclen = DIRSIZ(0, dp); + if (dirloc + dp->d_reclen > DIRBLKSIZ) { + ((struct direct *)(dirbuf + prev))->d_reclen = + DIRBLKSIZ - prev; + if ( fwrite(dirbuf, 1, DIRBLKSIZ, df) != DIRBLKSIZ ) + err(1,"cannot write to file %s", dirfile); + dirloc = 0; + } + memmove(dirbuf + dirloc, dp, (size_t)dp->d_reclen); + prev = dirloc; + dirloc += dp->d_reclen; +} + +/* + * flush out a directory that is finished. + */ +static void +flushent(void) +{ + ((struct direct *)(dirbuf + prev))->d_reclen = DIRBLKSIZ - prev; + if ( fwrite(dirbuf, (int)dirloc, 1, df) != 1 ) + err(1, "cannot write to file %s", dirfile); + seekpt = FTELL(df); + if (seekpt == -1) + err(1, "cannot write to file %s", dirfile); + dirloc = 0; +} + +static void +dcvt(struct odirect *odp, struct direct *ndp) +{ + + memset(ndp, 0, (size_t)(sizeof *ndp)); + ndp->d_ino = odp->d_ino; + ndp->d_type = DT_UNKNOWN; + (void) strncpy(ndp->d_name, odp->d_name, ODIRSIZ); + ndp->d_namlen = strlen(ndp->d_name); + ndp->d_reclen = DIRSIZ(0, ndp); +} + +/* + * Seek to an entry in a directory. + * Only values returned by rst_telldir should be passed to rst_seekdir. + * This routine handles many directories in a single file. + * It takes the base of the directory in the file, plus + * the desired seek offset into it. + */ +static void +rst_seekdir(RST_DIR *dirp, OFF_T loc, OFF_T base) +{ + + if (loc == rst_telldir(dirp)) + return; + loc -= base; + if (loc < 0) + fprintf(stderr, "bad seek pointer to rst_seekdir %lld\n", (long long int)loc); + (void) LSEEK(dirp->dd_fd, base + (loc & ~(DIRBLKSIZ - 1)), SEEK_SET); + dirp->dd_loc = loc & (DIRBLKSIZ - 1); + if (dirp->dd_loc != 0) + dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); +} + +/* + * get next entry in a directory. + */ +struct direct * +rst_readdir(RST_DIR *dirp) +{ + struct direct *dp; + + for (;;) { + if (dirp->dd_loc == 0) { + dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, + DIRBLKSIZ); + if (dirp->dd_size <= 0) { + Dprintf(stderr, "error reading directory\n"); + return (NULL); + } + } + if (dirp->dd_loc >= dirp->dd_size) { + dirp->dd_loc = 0; + continue; + } + dp = (struct direct *)(dirp->dd_buf + dirp->dd_loc); + if (dp->d_reclen == 0 || + dp->d_reclen > DIRBLKSIZ + 1 - dirp->dd_loc) { + Dprintf(stderr, "corrupted directory: bad reclen %d\n", + dp->d_reclen); + return (NULL); + } + dirp->dd_loc += dp->d_reclen; + if (dp->d_ino == 0 && strcmp(dp->d_name, "/") == 0) + return (NULL); + if (dp->d_ino >= maxino) { + Dprintf(stderr, "corrupted directory: bad inum %d\n", + dp->d_ino); + continue; + } + return (dp); + } +} + +/* + * Simulate the opening of a directory + */ +RST_DIR * +rst_opendir(const char *name) +{ + struct inotab *itp; + RST_DIR *dirp; + dump_ino_t ino; + + if ((ino = dirlookup(name)) > 0 && + (itp = inotablookup(ino)) != NULL) { + dirp = opendirfile(dirfile); + rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); + return (dirp); + } + return (NULL); +} + +/* + * In our case, there is nothing to do when closing a directory. + */ +void +rst_closedir(RST_DIR *dirp) +{ + + (void)close(dirp->dd_fd); + free(dirp); + return; +} + +/* + * Simulate finding the current offset in the directory. + */ +static OFF_T +rst_telldir(RST_DIR *dirp) +{ + return ((OFF_T)LSEEK(dirp->dd_fd, + (OFF_T)0, SEEK_CUR) - dirp->dd_size + dirp->dd_loc); +} + +/* + * Open a directory file. + */ +static RST_DIR * +opendirfile(const char *name) +{ + RST_DIR *dirp; + int fd; + + if ((fd = OPEN(name, O_RDONLY)) == -1) + return (NULL); + if ((dirp = malloc(sizeof(RST_DIR))) == NULL) { + (void)close(fd); + return (NULL); + } + dirp->dd_fd = fd; + dirp->dd_loc = 0; + return (dirp); +} + +/* + * Set the mode, owner, and times for all new or changed directories + */ +void +setdirmodes(int flags) +{ + FILE *mf; + struct modeinfo node; + struct entry *ep; + char *cp; + + Vprintf(stdout, "Set directory mode, owner, and times.\n"); + if (command == 'r' || command == 'R') + (void) snprintf(modefile, sizeof(modefile), "%s/rstmode%lu", tmpdir, (long)dumpdate); + if (modefile[0] == '#') { + panic("modefile not defined\n"); + fprintf(stderr, "directory mode, owner, and times not set\n"); + return; + } + mf = fopen(modefile, "r"); + if (mf == NULL) { + warn("fopen"); + fprintf(stderr, "cannot open mode file %s\n", modefile); + fprintf(stderr, "directory mode, owner, and times not set\n"); + return; + } + clearerr(mf); + for (;;) { + (void) fread((char *)&node, 1, sizeof(struct modeinfo), mf); + if (feof(mf)) + break; + ep = lookupino(node.ino); + if (command == 'i' || command == 'x') { + if (ep == NULL) + continue; + if ((flags & FORCE) == 0 && ep->e_flags & EXISTED) { + ep->e_flags &= ~NEW; + continue; + } + if ((flags & FORCE) == 0 && + node.ino == ROOTINO && + reply("set owner/mode for '.'") == FAIL) + continue; + } + if (ep == NULL) { + panic("cannot find directory inode %d\n", node.ino); + } else { + cp = myname(ep); + (void) chown(cp, node.uid, node.gid); + (void) chmod(cp, node.mode); + if (node.flags) +#ifdef __linux__ + (void) fsetflags(cp, node.flags); +#else +#ifdef sunos +#else + (void) chflags(cp, node.flags); +#endif +#endif + utimes(cp, node.timep); + ep->e_flags &= ~NEW; + } + } + if (ferror(mf)) + panic("error setting directory modes\n"); + (void) fclose(mf); +} + +/* + * Generate a literal copy of a directory. + */ +int +genliteraldir(char *name, dump_ino_t ino) +{ + struct inotab *itp; + int ofile, dp, i, size; + char buf[BUFSIZ]; + + itp = inotablookup(ino); + if (itp == NULL) + panic("Cannot find directory inode %d named %s\n", ino, name); + if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + warn("%s: cannot create file\n", name); + return (FAIL); + } + rst_seekdir(dirp, itp->t_seekpt, itp->t_seekpt); + dp = dup(dirp->dd_fd); + for (i = itp->t_size; i > 0; i -= BUFSIZ) { + size = i < BUFSIZ ? i : BUFSIZ; + if (read(dp, buf, (int) size) == -1) { + warnx("write error extracting inode %lu, name %s\n", + (unsigned long)curfile.ino, curfile.name); + err(1, "read"); + } + if (!Nflag && write(ofile, buf, (int) size) == -1) { + warnx("write error extracting inode %lu, name %s\n", + (unsigned long)curfile.ino, curfile.name); + err(1, "write"); + } + } + (void) close(dp); + (void) close(ofile); + return (GOOD); +} + +/* + * Determine the type of an inode + */ +int +inodetype(dump_ino_t ino) +{ + struct inotab *itp; + + itp = inotablookup(ino); + if (itp == NULL) + return (LEAF); + return (NODE); +} + +/* + * Allocate and initialize a directory inode entry. + * If requested, save its pertinent mode, owner, and time info. + */ +static struct inotab * +#if defined(__linux__) || defined(sunos) +allocinotab(dump_ino_t ino, struct new_bsd_inode *dip, OFF_T seekpt) +#else +allocinotab(dump_ino_t ino, struct dinode *dip, OFF_T seekpt) +#endif +{ + struct inotab *itp; + struct modeinfo node; + + itp = calloc(1, sizeof(struct inotab)); + if (itp == NULL) + panic("no memory directory table\n"); + itp->t_next = inotab[INOHASH(ino)]; + inotab[INOHASH(ino)] = itp; + itp->t_ino = ino; + itp->t_seekpt = seekpt; + if (mf == NULL) + return (itp); + node.ino = ino; +#if defined(__linux__) || defined(sunos) + node.timep[0].tv_sec = dip->di_atime.tv_sec; + node.timep[0].tv_usec = dip->di_atime.tv_usec; + node.timep[1].tv_sec = dip->di_mtime.tv_sec; + node.timep[1].tv_usec = dip->di_mtime.tv_usec; +#else /* __linux__ || sunos */ + node.timep[0].tv_sec = dip->di_atime; + node.timep[0].tv_usec = dip->di_atimensec / 1000; + node.timep[1].tv_sec = dip->di_mtime; + node.timep[1].tv_usec = dip->di_mtimensec / 1000; +#endif /* __linux__ || sunos */ + node.mode = dip->di_mode; + node.flags = dip->di_flags; + node.uid = dip->di_uid; + node.gid = dip->di_gid; + if ( fwrite((char *)&node, 1, sizeof(struct modeinfo), mf) != sizeof(struct modeinfo) ) + err(1,"cannot write to file %s", modefile); + return (itp); +} + +/* + * Look up an inode in the table of directories + */ +static struct inotab * +inotablookup(dump_ino_t ino) +{ + struct inotab *itp; + + for (itp = inotab[INOHASH(ino)]; itp != NULL; itp = itp->t_next) + if (itp->t_ino == ino) + return (itp); + return (NULL); +} + +/* + * Clean up and exit + */ +void +cleanup(void) +{ + closemt(); + if (modefile[0] != '#') + (void) unlink(modefile); + if (dirfile[0] != '#') + (void) unlink(dirfile); +} diff --git a/restore/extern.h b/restore/extern.h new file mode 100644 index 0000000..e2702ed --- /dev/null +++ b/restore/extern.h @@ -0,0 +1,156 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: extern.h,v 1.23 2003/10/26 16:05:48 stelian Exp $ + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#ifndef __P +#include +#endif +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif + +struct entry *addentry __P((char *, dump_ino_t, int)); +long addfile __P((char *, dump_ino_t, int)); +int addwhiteout __P((char *)); +void badentry __P((struct entry *, const char *)); +void canon __P((char *, char *, int)); +void checkrestore __P((void)); +void closemt __P((void)); +void cleanup __P((void)); +void comparefile __P((char *)); +void compareleaves __P((void)); +void createfiles __P((void)); +void createleaves __P((char *)); +void createlinks __P((void)); +long deletefile __P((char *, dump_ino_t, int)); +void deleteino __P((dump_ino_t)); +void delwhiteout __P((struct entry *)); +dump_ino_t dirlookup __P((const char *)); +void dumpsymtable __P((char *, long)); +void extractdirs __P((int)); +int extractfile __P((struct entry *, int)); +void findunreflinks __P((void)); +char *flagvalues __P((struct entry *)); +void freeentry __P((struct entry *)); +void freename __P((char *)); +int genliteraldir __P((char *, dump_ino_t)); +char *gentempname __P((struct entry *)); +void getfile __P((void (*)(char *, size_t), void (*)(char *, size_t))); +void getvol __P((long)); +void initsymtable __P((char *)); +int inodetype __P((dump_ino_t)); +int linkit __P((char *, char *, int)); +struct entry *lookupino __P((dump_ino_t)); +struct entry *lookupname __P((char *)); +long listfile __P((char *, dump_ino_t, int)); +dump_ino_t lowerbnd __P((dump_ino_t)); +void mktempname __P((struct entry *)); +void moveentry __P((struct entry *, char *)); +void msg __P((const char *, ...)); +char *myname __P((struct entry *)); +void newnode __P((struct entry *)); +void newtapebuf __P((long)); +long nodeupdates __P((char *, dump_ino_t, int)); +void onintr __P((int)); +void panic __P((const char *, ...)); +void pathcheck __P((char *)); +struct direct *pathsearch __P((const char *)); +void printdumpinfo __P((void)); +void printvolinfo __P((void)); +void removeleaf __P((struct entry *)); +void removenode __P((struct entry *)); +void removeoldleaves __P((void)); +void removeoldnodes __P((void)); +void renameit __P((char *, char *)); +int reply __P((const char *)); +void resizemaps __P((dump_ino_t, dump_ino_t)); +RST_DIR *rst_opendir __P((const char *)); +struct direct *rst_readdir __P((RST_DIR *)); +void rst_closedir __P((RST_DIR *dirp)); +void runcmdshell __P((void)); +char *savename __P((char *)); +void setdirmodes __P((int)); +void setinput __P((char *)); +void setup __P((void)); +void skipdirs __P((void)); +void skipfile __P((void)); +void skipmaps __P((void)); +void swabst __P((u_char *, u_char *)); +void treescan __P((char *, dump_ino_t, long (*)(char *, dump_ino_t, int))); +dump_ino_t upperbnd __P((dump_ino_t)); +long verifyfile __P((char *, dump_ino_t, int)); +void xtrnull __P((char *, size_t)); + +/* From ../dump/dumprmt.c */ +void rmtclose __P((void)); +int rmthost __P((const char *)); +int rmtioctl __P((int, int)); +int rmtopen __P((const char *, const int)); +int rmtread __P((const char *, int)); +OFF_T rmtseek __P((OFF_T, int)); + +/* From e2fsprogs */ +int fsetflags __P((const char *, unsigned long)); +int fgetflags __P((const char *, unsigned long *)); +int setflags __P((int, unsigned long)); + +#ifdef USE_QFA +int Inode2Tapepos __P((dump_ino_t, long *, long long *, int)); +int GetTapePos __P((long long *)); +int GotoTapePos __P((long long)); +void ReReadFromTape __P((void)); +void ReReadInodeFromTape __P((dump_ino_t)); +void GetPathFile __P((char *, char *, char *)); + +#ifdef sunos +int GetSCSIIDFromPath __P((char *, long *)); +int OpenSMTCmt(char *); +#endif +#endif +void RequestVol __P((long)); + +#ifdef DUMP_MACOSX +int extractfinderinfoufs __P((char *)); +int extractresourceufs __P((char *)); +int CreateAppleDoubleFileRes __P((char *, FndrFileInfo *, mode_t, int, struct timeval *, u_int32_t, u_int32_t)); +#endif + + + diff --git a/restore/interactive.c b/restore/interactive.c new file mode 100644 index 0000000..ecbffda --- /dev/null +++ b/restore/interactive.c @@ -0,0 +1,1042 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: interactive.c,v 1.27 2003/10/26 16:05:48 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#ifdef __linux__ +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#else +#include +#include +#endif +#endif /* __linux__ */ +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#endif + +#if defined(__linux__) || defined(sunos) +extern char * __progname; +#endif + +#include "restore.h" +#include "extern.h" + +#if HAVE_READLINE +#include +#include + +static char *rl_gets (char *prompt); +static void initialize_readline(void); +static char **restore_completion (const char *text, int start, int end); +static char *command_generator(const char *text, int state); +static char *filename_generator(const char *text, int state); +#endif + +#define round(a, b) (((a) + (b) - 1) / (b) * (b)) + +/* + * Things to handle interruptions. + */ +static int runshell; +static jmp_buf reset; +static char *nextarg = NULL; +static int pflag = 0; /* prompt mode */ +/* + * Structure and routines associated with listing directories. + */ +struct afile { + dump_ino_t fnum; /* inode number of file */ + char *fname; /* file name */ + short len; /* name length */ + char prefix; /* prefix character */ + char postfix; /* postfix character */ +}; +struct arglist { + int freeglob; /* glob structure needs to be freed */ + int argcnt; /* next globbed argument to return */ + glob_t glob; /* globbing information */ + char *cmd; /* the current command */ +}; + +static char *copynext __P((char *, char *)); +static int fcmp __P((const void *, const void *)); +static void formatf __P((struct afile *, int)); +static void getcmd __P((char *, char *, char *, int, struct arglist *)); +struct dirent *glob_readdir __P((RST_DIR *dirp)); +static int glob_stat __P((const char *, struct stat *)); +static void mkentry __P((char *, struct direct *, struct afile *)); +static void printlist __P((char *, char *)); + +/* + * Read and execute commands from the terminal. + */ +void +runcmdshell(void) +{ + struct entry *np; + dump_ino_t ino; + struct arglist arglist; + char curdir[MAXPATHLEN]; + char name[MAXPATHLEN]; + char cmd[BUFSIZ]; + +#if HAVE_READLINE + initialize_readline(); +#endif + arglist.freeglob = 0; + arglist.argcnt = 0; + arglist.glob.gl_flags = GLOB_ALTDIRFUNC; + arglist.glob.gl_opendir = (void *)rst_opendir; + arglist.glob.gl_readdir = (void *)glob_readdir; + arglist.glob.gl_closedir = (void *)rst_closedir; + arglist.glob.gl_lstat = (int (*)(const char *, void *))glob_stat; + arglist.glob.gl_stat = (int (*)(const char *, void *))glob_stat; + canon("/", curdir, sizeof(curdir)); +loop: + if (setjmp(reset) != 0) { + if (arglist.freeglob != 0) { + arglist.freeglob = 0; + arglist.argcnt = 0; + globfree(&arglist.glob); + } + nextarg = NULL; + volno = 0; + } + runshell = 1; + getcmd(curdir, cmd, name, sizeof(name), &arglist); + switch (cmd[0]) { + /* + * Add elements to the extraction list. + */ + case 'a': + if (strncmp(cmd, "add", strlen(cmd)) != 0) + goto bad; + ino = dirlookup(name); + if (ino == 0) + break; + if (mflag) + pathcheck(name); + treescan(name, ino, addfile); + break; + /* + * Change working directory. + */ + case 'c': + if (strncmp(cmd, "cd", strlen(cmd)) != 0) + goto bad; + ino = dirlookup(name); + if (ino == 0) + break; + if (inodetype(ino) == LEAF) { + fprintf(stderr, "%s: not a directory\n", name); + break; + } + (void) strncpy(curdir, name, sizeof(curdir)); + curdir[sizeof(curdir) - 1] = '\0'; + break; + /* + * Delete elements from the extraction list. + */ + case 'd': + if (strncmp(cmd, "delete", strlen(cmd)) != 0) + goto bad; + np = lookupname(name); + if (np == NULL || (np->e_flags & NEW) == 0) { + fprintf(stderr, "%s: not on extraction list\n", name); + break; + } + treescan(name, np->e_ino, deletefile); + break; + /* + * Extract the requested list. + */ + case 'e': + if (strncmp(cmd, "extract", strlen(cmd)) != 0) + goto bad; + createfiles(); + createlinks(); + setdirmodes(oflag ? FORCE : 0); + if (dflag) + checkrestore(); + volno = 0; + break; + /* + * List available commands. + */ + case 'h': + if (strncmp(cmd, "help", strlen(cmd)) != 0) + goto bad; + case '?': + fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "Available commands are:\n", + "\tls [arg] - list directory\n", + "\tcd arg - change directory\n", + "\tpwd - print current directory\n", + "\tadd [arg] - add `arg' to list of", + " files to be extracted\n", + "\tdelete [arg] - delete `arg' from", + " list of files to be extracted\n", + "\textract - extract requested files\n", + "\tsetmodes - set modes of requested directories\n", + "\tquit - immediately exit program\n", + "\twhat - list dump header information\n", + "\tverbose - toggle verbose flag", + " (useful with ``ls'')\n", + "\tprompt - toggle the prompt display\n", + "\thelp or `?' - print this list\n", + "If no `arg' is supplied, the current", + " directory is used\n"); + break; + /* + * List a directory. + */ + case 'l': + if (strncmp(cmd, "ls", strlen(cmd)) != 0) + goto bad; + printlist(name, curdir); + break; + /* + * Print current directory. + */ + case 'p': + if (strncmp(cmd, "pwd", strlen(cmd)) == 0) { + if (curdir[1] == '\0') + fprintf(stderr, "/\n"); + else + fprintf(stderr, "%s\n", &curdir[1]); + } + /* + * Toggle prompt mode. + */ + else if (strncmp(cmd, "prompt", strlen(cmd)) == 0) { + if (pflag) { + fprintf(stderr, "prompt mode off\n"); + pflag = 0; + break; + } + fprintf(stderr, "prompt mode on\n"); + pflag++; + break; + } + else goto bad; + break; + /* + * Quit. + */ + case 'q': + if (strncmp(cmd, "quit", strlen(cmd)) != 0) + goto bad; + return; + case 'x': + if (strncmp(cmd, "xit", strlen(cmd)) != 0) + goto bad; + return; + /* + * Toggle verbose mode. + */ + case 'v': + if (strncmp(cmd, "verbose", strlen(cmd)) != 0) + goto bad; + if (vflag) { + fprintf(stderr, "verbose mode off\n"); + vflag = 0; + break; + } + fprintf(stderr, "verbose mode on\n"); + vflag++; + break; + /* + * Just restore requested directory modes. + */ + case 's': + if (strncmp(cmd, "setmodes", strlen(cmd)) != 0) + goto bad; + setdirmodes(FORCE); + break; + /* + * Print out dump header information. + */ + case 'w': + if (strncmp(cmd, "what", strlen(cmd)) != 0) + goto bad; + printdumpinfo(); + printvolinfo(); + break; + /* + * Turn on debugging. + */ + case 'D': + if (strncmp(cmd, "Debug", strlen(cmd)) != 0) + goto bad; + if (dflag) { + fprintf(stderr, "debugging mode off\n"); + dflag = 0; + break; + } + fprintf(stderr, "debugging mode on\n"); + dflag++; + break; + /* + * Unknown command. + */ + default: + bad: + fprintf(stderr, "%s: unknown command; type ? for help\n", cmd); + break; + } + goto loop; +} + +/* + * Read and parse an interactive command. + * The first word on the line is assigned to "cmd". If + * there are no arguments on the command line, then "curdir" + * is returned as the argument. If there are arguments + * on the line they are returned one at a time on each + * successive call to getcmd. Each argument is first assigned + * to "name". If it does not start with "/" the pathname in + * "curdir" is prepended to it. Finally "canon" is called to + * eliminate any embedded ".." components. + */ +static void +getcmd(char *curdir, char *cmd, char *name, int size, struct arglist *ap) +{ + char *cp; + static char input[BUFSIZ]; + char output[BUFSIZ]; +# define rawname input /* save space by reusing input buffer */ + + /* + * Check to see if still processing arguments. + */ + if (ap->argcnt > 0) + goto retnext; + if (nextarg != NULL) + goto getnext; + /* + * Read a command line and trim off trailing white space. + */ +#if HAVE_READLINE + snprintf(input, BUFSIZ, "%s\n", rl_gets(curdir)); +#else + do { + if (pflag) + fprintf(stderr, "%s:%s:%s > ", + __progname, + spcl.c_filesys, + curdir[1] ? &curdir[1] : "/"); + else + fprintf(stderr, "%s > ", __progname); + (void) fflush(stderr); + (void) fgets(input, BUFSIZ, terminal); + } while (!feof(terminal) && input[0] == '\n'); + if (feof(terminal)) { + (void) strcpy(cmd, "quit"); + return; + } +#endif + for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--) + /* trim off trailing white space and newline */; + *++cp = '\0'; + /* + * Copy the command into "cmd". + */ + cp = copynext(input, cmd); + ap->cmd = cmd; + /* + * If no argument, use curdir as the default. + */ + if (*cp == '\0') { + (void) strncpy(name, curdir, size); + name[size - 1] = '\0'; + return; + } + nextarg = cp; + /* + * Find the next argument. + */ +getnext: + cp = copynext(nextarg, rawname); + if (*cp == '\0') + nextarg = NULL; + else + nextarg = cp; + /* + * If it is an absolute pathname, canonicalize it and return it. + */ + if (rawname[0] == '/') { + canon(rawname, name, size); + } else { + /* + * For relative pathnames, prepend the current directory to + * it then canonicalize and return it. + */ + snprintf(output, sizeof(output), "%s/%s", curdir, rawname); + canon(output, name, size); + } + if (glob(name, GLOB_ALTDIRFUNC, NULL, &ap->glob) < 0) + fprintf(stderr, "%s: out of memory\n", ap->cmd); + if (ap->glob.gl_pathc == 0) + return; + ap->freeglob = 1; + ap->argcnt = ap->glob.gl_pathc; + +retnext: + strncpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt], size); + name[size - 1] = '\0'; + if (--ap->argcnt == 0) { + ap->freeglob = 0; + globfree(&ap->glob); + } +# undef rawname +} + +/* + * Strip off the next token of the input. + */ +static char * +copynext(char *input, char *output) +{ + char *cp, *bp; + char quote; + + for (cp = input; *cp == ' ' || *cp == '\t'; cp++) + /* skip to argument */; + bp = output; + while (*cp != ' ' && *cp != '\t' && *cp != '\0') { + /* + * Handle back slashes. + */ + if (*cp == '\\') { + if (*++cp == '\0') { + fprintf(stderr, + "command lines cannot be continued\n"); + continue; + } + *bp++ = *cp++; + continue; + } + /* + * The usual unquoted case. + */ + if (*cp != '\'' && *cp != '"') { + *bp++ = *cp++; + continue; + } + /* + * Handle single and double quotes. + */ + quote = *cp++; + while (*cp != quote && *cp != '\0') + *bp++ = *cp++; + if (*cp++ == '\0') { + fprintf(stderr, "missing %c\n", quote); + cp--; + continue; + } + } + *bp = '\0'; + return (cp); +} + +/* + * Canonicalize file names to always start with ``./'' and + * remove any embedded "." and ".." components. + */ +void +canon(char *rawname, char *canonname, int len) +{ + char *cp, *np; + + if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0) + (void) strcpy(canonname, ""); + else if (rawname[0] == '/') + (void) strcpy(canonname, "."); + else + (void) strcpy(canonname, "./"); + if (strlen(canonname) + strlen(rawname) >= (unsigned)len) + errx(1, "canonname: not enough buffer space"); + + (void) strcat(canonname, rawname); + /* + * Eliminate multiple and trailing '/'s + */ + for (cp = np = canonname; *np != '\0'; cp++) { + *cp = *np++; + while (*cp == '/' && *np == '/') + np++; + } + *cp = '\0'; + if (*--cp == '/') + *cp = '\0'; + /* + * Eliminate extraneous "." and ".." from pathnames. + */ + for (np = canonname; *np != '\0'; ) { + np++; + cp = np; + while (*np != '/' && *np != '\0') + np++; + if (np - cp == 1 && *cp == '.') { + cp--; + (void) strcpy(cp, np); + np = cp; + } + if (np - cp == 2 && strncmp(cp, "..", 2) == 0) { + cp--; + while (cp > &canonname[1] && *--cp != '/') + /* find beginning of name */; + (void) strcpy(cp, np); + np = cp; + } + } +} + +/* + * Do an "ls" style listing of a directory + */ +static void +printlist(char *name, char *basename) +{ + struct afile *fp, *list, *listp = NULL; + struct direct *dp; + struct afile single; + RST_DIR *dirp; + int entries, len, namelen; + char locname[MAXPATHLEN + 1]; + + dp = pathsearch(name); + if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) || + (!vflag && dp->d_ino == WINO)) + return; + if ((dirp = rst_opendir(name)) == NULL) { + entries = 1; + list = &single; + mkentry(name, dp, list); + len = strlen(basename) + 1; + if (strlen(name) - len > (unsigned)single.len) { + freename(single.fname); + single.fname = savename(&name[len]); + single.len = strlen(single.fname); + } + } else { + entries = 0; + while ((dp = rst_readdir(dirp))) + entries++; + rst_closedir(dirp); + list = (struct afile *)malloc(entries * sizeof(struct afile)); + if (list == NULL) { + fprintf(stderr, "ls: out of memory\n"); + return; + } + if ((dirp = rst_opendir(name)) == NULL) + panic("directory reopen failed\n"); + fprintf(stderr, "%s:\n", name); + entries = 0; + listp = list; + namelen = snprintf(locname, sizeof(locname), "%s/", name); + if (namelen >= (int)sizeof(locname)) + namelen = sizeof(locname) - 1; + while ((dp = rst_readdir(dirp))) { + if (dp == NULL) + break; + if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) + continue; + if (!vflag && (dp->d_ino == WINO || + strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0)) + continue; + locname[namelen] = '\0'; + if (namelen + strlen(dp->d_name) >= MAXPATHLEN) { + fprintf(stderr, "%s%s: name exceeds %d char\n", + locname, dp->d_name, MAXPATHLEN); + } else { + (void) strncat(locname, dp->d_name, + (int)strlen(dp->d_name)); + mkentry(locname, dp, listp++); + entries++; + } + } + rst_closedir(dirp); + if (entries == 0) { + fprintf(stderr, "\n"); + free(list); + return; + } + qsort((char *)list, entries, sizeof(struct afile), fcmp); + } + formatf(list, entries); + if (dirp != NULL) { + for (fp = listp - 1; fp >= list; fp--) + freename(fp->fname); + fprintf(stderr, "\n"); + free(list); + } +} + +/* + * Read the contents of a directory. + */ +static void +mkentry(char *name, struct direct *dp, struct afile *fp) +{ + char *cp; + struct entry *np; + + fp->fnum = dp->d_ino; + fp->fname = savename(dp->d_name); + for (cp = fp->fname; *cp; cp++) + if (!vflag && (*cp < ' ' || *cp >= 0177)) + *cp = '?'; + fp->len = cp - fp->fname; + if (dflag && TSTINO(fp->fnum, dumpmap) == 0) + fp->prefix = '^'; + else if ((np = lookupname(name)) != NULL && (np->e_flags & NEW)) + fp->prefix = '*'; + else + fp->prefix = ' '; + switch(dp->d_type) { + + default: + fprintf(stderr, "Warning: undefined file type %d\n", + dp->d_type); + /* fall through */ + case DT_REG: + fp->postfix = ' '; + break; + + case DT_LNK: + fp->postfix = '@'; + break; + + case DT_FIFO: + case DT_SOCK: + fp->postfix = '='; + break; + + case DT_CHR: + case DT_BLK: + fp->postfix = '#'; + break; + +#ifndef __linux__ + /* no need for this */ + case DT_WHT: + fp->postfix = '%'; + break; +#endif + + case DT_UNKNOWN: + case DT_DIR: + if (inodetype(dp->d_ino) == NODE) + fp->postfix = '/'; + else + fp->postfix = ' '; + break; + } + return; +} + +/* + * Print out a pretty listing of a directory + */ +static void +formatf(struct afile *list, int nentry) +{ + struct afile *fp, *endlist; + int width, bigino, haveprefix, havepostfix; + int i, j, w, precision = 0, columns, lines; + + width = 0; + haveprefix = 0; + havepostfix = 0; + bigino = ROOTINO; + endlist = &list[nentry]; + for (fp = &list[0]; fp < endlist; fp++) { + if (bigino < (int)fp->fnum) + bigino = fp->fnum; + if (width < fp->len) + width = fp->len; + if (fp->prefix != ' ') + haveprefix = 1; + if (fp->postfix != ' ') + havepostfix = 1; + } + if (haveprefix) + width++; + if (havepostfix) + width++; + if (vflag) { + for (precision = 0, i = bigino; i > 0; i /= 10) + precision++; + width += precision + 1; + } + width++; + columns = 81 / width; + if (columns == 0) + columns = 1; + lines = (nentry + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + fp = &list[j * lines + i]; + if (vflag) { + fprintf(stderr, "%*ld ", precision, (long)fp->fnum); + fp->len += precision + 1; + } + if (haveprefix) { + putc(fp->prefix, stderr); + fp->len++; + } + fprintf(stderr, "%s", fp->fname); + if (havepostfix) { + putc(fp->postfix, stderr); + fp->len++; + } + if (fp + lines >= endlist) { + fprintf(stderr, "\n"); + break; + } + for (w = fp->len; w < width; w++) + putc(' ', stderr); + } + } +} + +/* + * Skip over directory entries that are not on the tape + * + * First have to get definition of a dirent. + * + * For Linux the dirent struct is now included from bsdcompat.h + */ +#ifndef __linux__ +#undef DIRBLKSIZ +#include +#undef d_ino +#endif /* ! __linux__ */ + +struct dirent * +glob_readdir(RST_DIR *dirp) +{ + struct direct *dp; + static struct dirent adirent; + + while ((dp = rst_readdir(dirp)) != NULL) { + if (!vflag && dp->d_ino == WINO) + continue; + if (dflag || TSTINO(dp->d_ino, dumpmap)) + break; + } + if (dp == NULL) + return (NULL); + adirent.d_fileno = dp->d_ino; + memmove(adirent.d_name, dp->d_name, dp->d_namlen + 1); + return (&adirent); +} + +/* + * Return st_mode information in response to stat or lstat calls + */ +static int +glob_stat(const char *name, struct stat *stp) +{ + struct direct *dp; + dp = pathsearch(name); + if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) || + (!vflag && dp->d_ino == WINO)) + return (-1); + if (inodetype(dp->d_ino) == NODE) + stp->st_mode = IFDIR; + else + stp->st_mode = IFREG; + return (0); +} + +/* + * Comparison routine for qsort. + */ +static int +fcmp(const void *f1, const void *f2) +{ + return (strcmp(((struct afile *)f1)->fname, + ((struct afile *)f2)->fname)); +} + +/* + * respond to interrupts + */ +void +onintr(UNUSED(int signo)) +{ + int save_errno = errno; + + if (command == 'i' && runshell) + longjmp(reset, 1); + if (reply("restore interrupted, continue") == FAIL) + exit(1); + errno = save_errno; +} + + +#if HAVE_READLINE + +#if !HAVE_READLINE_RLCM +#define rl_completion_matches completion_matches +#endif + +/* A static variable for holding the line. */ +static char *line_read = NULL; + +static char completion_curdir[MAXPATHLEN]; + +static char *commands[] = { + "add ", "cd ", "delete ", "extract ", "help ", + "? ", "ls ", "pwd ", "prompt ", "quit ", "xit ", + "verbose ", "setmodes ", "what ", "Debug ", + NULL }; + +static char *files = NULL; + +static char * +rl_gets (char *dir) +{ + char *prompt; + int sz; + + snprintf(completion_curdir, MAXPATHLEN, "%s", dir); + completion_curdir[MAXPATHLEN - 1] = '\0'; + + if (pflag) { + sz = 6 + strlen(__progname) + strlen(spcl.c_filesys) + strlen((completion_curdir + 1 ? completion_curdir + 1 : "/")); + prompt = (char *)malloc(sz); + if (!prompt) + return NULL; + snprintf(prompt, sz, "%s:%s:%s > ", + __progname, + spcl.c_filesys, + (completion_curdir + 1 ? completion_curdir + 1 : "/")); + } + else { + sz = 4 + strlen(__progname); + prompt = (char *)malloc(sz); + if (!prompt) + return NULL; + snprintf(prompt, sz, "%s > ", __progname); + } + prompt[sz - 1] = '\0'; + + if (line_read) { + free (line_read); + line_read = (char *)NULL; + } + + do { + line_read = readline (prompt); + } while (line_read && !*line_read); + + free(prompt); + + if (!line_read) { + printf("\n"); + return strdup("quit"); + } + + add_history (line_read); + + return (line_read); +} + +static char * +command_generator(const char *text, int state) +{ + static int list_index, len; + char *name; + + if (!state) { + list_index = 0; + len = strlen(text); + } + + while ( (name = commands[list_index]) != NULL) { + + list_index ++; + + if (strncmp(name, text, len) == 0) + return strdup(name); + } + + return NULL; +} + +static char * +filename_generator(const char *text, int state) +{ + static int list_index; + char *name; + RST_DIR *dirp; + struct direct *dp; + static int entries; + char pname[MAXPATHLEN]; + char fname[MAXPATHLEN]; + char *slash; + char ppname[MAXPATHLEN]; + + if (!state) { + list_index = 0; + + if (files != NULL) { + free(files); + entries = 0; + files = NULL; + } + if ((slash = strrchr(text, '/')) != NULL) { + int idx = slash - text; + if (idx > MAXPATHLEN - 2) + idx = MAXPATHLEN - 2; + strncpy(ppname, text, MAXPATHLEN); + ppname[MAXPATHLEN - 1] = '\0'; + ppname[idx] = '\0'; + if (text[0] == '/') + snprintf(pname, MAXPATHLEN, ".%s", ppname); + else + snprintf(pname, MAXPATHLEN, "%s/%s", completion_curdir, ppname); + strncpy(fname, ppname + idx + 1, MAXPATHLEN); + ppname[idx] = '/'; + ppname[idx + 1] = '\0'; + } + else { + strncpy(pname, completion_curdir, MAXPATHLEN); + strncpy(fname, text, MAXPATHLEN); + ppname[0] = '\0'; + } + pname[MAXPATHLEN - 1] = '\0'; + fname[MAXPATHLEN - 1] = '\0'; + if ((dirp = rst_opendir(pname)) == NULL) + return NULL; + entries = 0; + while ((dp = rst_readdir(dirp))) + entries++; + rst_closedir(dirp); + files = (char *)malloc(entries * MAXPATHLEN); + if (files == NULL) { + fprintf(stderr, "Out of memory\n"); + entries = 0; + return NULL; + } + if ((dirp = rst_opendir(pname)) == NULL) + panic("directory reopen failed\n"); + entries = 0; + while ((dp = rst_readdir(dirp))) { + if (TSTINO(dp->d_ino, dumpmap) == 0) + continue; + if (strcmp(dp->d_name, ".") == 0 || + strcmp(dp->d_name, "..") == 0) + continue; + if (strncmp(dp->d_name, fname, strlen(fname)) == 0) { + if (inodetype(dp->d_ino) == NODE) + snprintf(files + entries * MAXPATHLEN, MAXPATHLEN, "%s%s/", ppname, dp->d_name); + else + snprintf(files + entries * MAXPATHLEN, MAXPATHLEN, "%s%s ", ppname, dp->d_name); + *(files + (entries + 1) * MAXPATHLEN - 1) = '\0'; + ++entries; + } + } + rst_closedir(dirp); + } + + if (list_index >= entries) + return NULL; + + name = strdup(files + list_index * MAXPATHLEN); + list_index ++; + + return name; +} + +static char ** +restore_completion (const char *text, int start, UNUSED(int end)) +{ + char **matches; + + if (start == 0) + matches = rl_completion_matches (text, command_generator); + else + matches = rl_completion_matches (text, filename_generator); + + return (matches); +} + +static void +initialize_readline(void) +{ + rl_readline_name = "dump"; + rl_attempted_completion_function = restore_completion; + rl_completion_entry_function = NULL; +#if HAVE_READLINE_CAC /* compile with readline 2.0 */ + rl_completion_append_character = '\0'; +#endif + rl_instream = terminal; +} + +#endif /* HAVE_READLINE */ diff --git a/restore/main.c b/restore/main.c new file mode 100644 index 0000000..f53d740 --- /dev/null +++ b/restore/main.c @@ -0,0 +1,789 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: main.c,v 1.46 2004/04/13 13:04:33 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#include +#include +#include +#else +#include +#endif +#endif /* __linux__ */ +#include + +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#endif + +#include "pathnames.h" +#include "restore.h" +#include "extern.h" + +int abortifconnerr = 1; /* set to 1 if lib dumprmt.o should exit on connection errors + otherwise just print a message using msg */ + +int aflag = 0, bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; +int hflag = 1, mflag = 1, Mflag = 0, Nflag = 0, Vflag = 0, zflag = 0; +int uflag = 0, lflag = 0, Lflag = 0, oflag = 0; +int ufs2flag = 0; +char *Afile = NULL; +int dokerberos = 0; +char command = '\0'; +long dumpnum = 1; +long volno = 0; +long ntrec; +char *dumpmap = NULL; +char *usedinomap = NULL; +dump_ino_t maxino; +time_t dumptime; +time_t dumpdate; +FILE *terminal; +char *tmpdir; +int compare_ignore_not_found; +int compare_errors; +char filesys[NAMELEN]; +static const char *stdin_opt = NULL; +char *bot_script = NULL; +dump_ino_t volinfo[TP_NINOS]; + +#ifdef USE_QFA +FILE *gTapeposfp; +char *gTapeposfile; +char gTps[255]; +long gSeekstart; +int tapeposflag; +int gTapeposfd; +int createtapeposflag; +unsigned long qfadumpdate; +long long curtapepos; +#endif /* USE_QFA */ + +long smtc_errno; + +#if defined(__linux__) || defined(sunos) +char *__progname; +#endif + +static void obsolete __P((int *, char **[])); +static void usage __P((void)); +static void use_stdin __P((const char *)); + +#define FORCED_UMASK (077) + +int +main(int argc, char *argv[]) +{ + int ch; + dump_ino_t ino; + char *inputdev = _PATH_DEFTAPE; + char *symtbl = "./restoresymtable"; + char *p, name[MAXPATHLEN]; + FILE *filelist = NULL; + char fname[MAXPATHLEN]; + mode_t orig_umask; +#ifdef DEBUG_QFA + time_t tistart, tiend, titaken; +#endif +#ifdef USE_QFA + tapeposflag = 0; + createtapeposflag = 0; +#endif /* USE_QFA */ + + /* Temp files should *not* be readable. We set permissions later. */ + orig_umask = umask(FORCED_UMASK); + filesys[0] = '\0'; +#if defined(__linux__) || defined(sunos) + __progname = argv[0]; +#endif + + if (argc < 2) + usage(); + + if ((inputdev = getenv("TAPE")) == NULL) + inputdev = _PATH_DEFTAPE; + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = _PATH_TMP; + if ((tmpdir = strdup(tmpdir)) == NULL) + err(1, "malloc tmpdir"); + for (p = tmpdir + strlen(tmpdir) - 1; p >= tmpdir && *p == '/'; p--) + ; + obsolete(&argc, &argv); + while ((ch = getopt(argc, argv, + "aA:b:CcdD:f:F:hi" +#ifdef KERBEROS + "k" +#endif + "lL:mMNo" +#ifdef USE_QFA + "P:Q:" +#endif + "Rrs:tT:uvVxX:y")) != -1) + switch(ch) { + case 'a': + aflag = 1; + break; + case 'A': + Afile = optarg; + aflag = 1; + break; + case 'b': + /* Change default tape blocksize. */ + bflag = 1; + ntrec = strtol(optarg, &p, 10); + if (*p) + errx(1, "illegal blocksize -- %s", optarg); + if (ntrec <= 0) + errx(1, "block size must be greater than 0"); + break; + case 'c': + cvtflag = 1; + break; + case 'D': + strncpy(filesys, optarg, NAMELEN); + filesys[NAMELEN - 1] = '\0'; + break; + case 'T': + tmpdir = optarg; + break; + case 'd': + dflag = 1; + break; + case 'f': + if( !strcmp(optarg,"-") ) + use_stdin("-f"); + inputdev = optarg; + break; + case 'F': + bot_script = optarg; + break; + case 'h': + hflag = 0; + break; +#ifdef KERBEROS + case 'k': + dokerberos = 1; + break; +#endif + case 'C': + case 'i': +#ifdef USE_QFA + case 'P': +#endif + case 'R': + case 'r': + case 't': + case 'x': + if (command != '\0') + errx(1, + "%c and %c options are mutually exclusive", + ch, command); + command = ch; +#ifdef USE_QFA + if (ch == 'P') { + gTapeposfile = optarg; + createtapeposflag = 1; + } +#endif + + break; + case 'l': + lflag = 1; + break; + case 'L': + Lflag = strtol(optarg, &p, 10); + if (*p) + errx(1, "illegal limit -- %s", optarg); + if (Lflag < 0) + errx(1, "limit must be greater than 0"); + break; + case 'm': + mflag = 0; + break; + case 'M': + Mflag = 1; + break; + case 'N': + Nflag = 1; + break; + case 'o': + oflag = 1; + break; +#ifdef USE_QFA + case 'Q': + gTapeposfile = optarg; + tapeposflag = 1; + aflag = 1; + break; +#endif + case 's': + /* Dumpnum (skip to) for multifile dump tapes. */ + dumpnum = strtol(optarg, &p, 10); + if (*p) + errx(1, "illegal dump number -- %s", optarg); + if (dumpnum <= 0) + errx(1, "dump number must be greater than 0"); + break; + case 'u': + uflag = 1; + break; + case 'v': + vflag = 1; + break; + case 'V': + Vflag = 1; + break; + case 'X': + if( !strcmp(optarg,"-") ) { + use_stdin("-X"); + filelist = stdin; + } + else + if ( !(filelist = fopen(optarg,"r")) ) + errx(1, "can't open file for reading -- %s", optarg); + break; + case 'y': + yflag = 1; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (command == '\0') + errx(1, "none of C, i, R, r, t or x options specified"); + +#ifdef USE_QFA + if (!mflag && tapeposflag) + errx(1, "m and Q options are mutually exclusive"); + + if (tapeposflag && command != 'i' && command != 'x' && command != 't') + errx(1, "Q option is not valid for %c command", command); +#endif + + if (Afile && command != 'i' && command != 'x' && command != 't') + errx(1, "A option is not valid for %c command", command); + + if (signal(SIGINT, onintr) == SIG_IGN) + (void) signal(SIGINT, SIG_IGN); + if (signal(SIGTERM, onintr) == SIG_IGN) + (void) signal(SIGTERM, SIG_IGN); + setlinebuf(stderr); + + atexit(cleanup); + + if (command == 'C' && inputdev[0] != '/' && strcmp(inputdev, "-") +#ifdef RRESTORE + && !strchr(inputdev, ':') +#endif + ) { + /* since we chdir into the directory we are comparing + * to, we must retain the full tape path */ + char wd[MAXPATHLEN], fullpathinput[MAXPATHLEN]; + if (!getcwd(wd, MAXPATHLEN)) + err(1, "can't get current directory"); + snprintf(fullpathinput, MAXPATHLEN, "%s/%s", wd, inputdev); + fullpathinput[MAXPATHLEN - 1] = '\0'; + setinput(fullpathinput); + } + else + setinput(inputdev); + + if (argc == 0 && !filelist) { + argc = 1; + *--argv = "."; + } + +#ifdef USE_QFA + if (tapeposflag) { + msg("reading QFA positions from %s\n", gTapeposfile); + if ((gTapeposfp = fopen(gTapeposfile, "r")) == NULL) + errx(1, "can't open file for reading -- %s", + gTapeposfile); + /* start reading header info */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; /* delete end of line */ + if (strcmp(gTps, QFA_MAGIC) != 0) + errx(1, "not requested format of -- %s", gTapeposfile); + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + if (strcmp(gTps, QFA_VERSION) != 0) + errx(1, "not requested format of -- %s", gTapeposfile); + /* read dumpdate */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + qfadumpdate = atol(gTps); + /* read empty line */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + /* read table header line */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + /* end reading header info */ + /* tape position table starts here */ + gSeekstart = ftell(gTapeposfp); /* remember for later use */ +#ifdef sunos + if (GetSCSIIDFromPath(inputdev, &scsiid)) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + if (scsiid < 0) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + errx(1, "can't open smtc device: %s, %d\n", smtcpath, errno); + } +#endif + } +#endif /* USE_QFA */ + + switch (command) { + /* + * Compare contents of tape. + */ + case 'C': { + struct STAT stbuf; + + Vprintf(stdout, "Begin compare restore\n"); + compare_ignore_not_found = 0; + compare_errors = 0; + setup(); + printf("filesys = %s\n", filesys); + if (STAT(filesys, &stbuf) < 0) + err(1, "cannot stat directory %s", filesys); + if (chdir(filesys) < 0) + err(1, "cannot cd to %s", filesys); + compare_ignore_not_found = dumptime > 0; + initsymtable((char *)0); + extractdirs(0); + treescan(".", ROOTINO, nodeupdates); + compareleaves(); + checkrestore(); + if (compare_errors) { + printf("Some files were modified!\n"); + exit(2); + } + break; + } + + /* + * Interactive mode. + */ + case 'i': + setup(); + extractdirs(1); + initsymtable(NULL); + runcmdshell(); + break; + /* + * Incremental restoration of a file system. + */ + case 'r': + aflag = 1; /* in -r or -R mode, -a is default */ + setup(); + if (dumptime > 0) { + /* + * This is an incremental dump tape. + */ + Vprintf(stdout, "Begin incremental restore\n"); + initsymtable(symtbl); + extractdirs(1); + removeoldleaves(); + Vprintf(stdout, "Calculate node updates.\n"); + treescan(".", ROOTINO, nodeupdates); + findunreflinks(); + removeoldnodes(); + } else { + /* + * This is a level zero dump tape. + */ + Vprintf(stdout, "Begin level 0 restore\n"); + initsymtable((char *)0); + extractdirs(1); + Vprintf(stdout, "Calculate extraction list.\n"); + treescan(".", ROOTINO, nodeupdates); + } + createleaves(symtbl); + createlinks(); + setdirmodes(FORCE); + checkrestore(); + if (dflag) { + Vprintf(stdout, "Verify the directory structure\n"); + treescan(".", ROOTINO, verifyfile); + } + dumpsymtable(symtbl, (long)1); + break; + /* + * Resume an incremental file system restoration. + */ + case 'R': + aflag = 1; /* in -r or -R mode, -a is default */ + initsymtable(symtbl); + skipmaps(); + skipdirs(); + createleaves(symtbl); + createlinks(); + setdirmodes(FORCE); + checkrestore(); + dumpsymtable(symtbl, (long)1); + break; + +/* handle file names from either text file (-X) or the command line */ +#define NEXTFILE(p) \ + p = NULL; \ + if (argc) { \ + --argc; \ + p = *argv++; \ + } \ + else if (filelist) { \ + if ((p = fgets(fname, MAXPATHLEN, filelist))) { \ + if ( *p && *(p + strlen(p) - 1) == '\n' ) /* possible null string */ \ + *(p + strlen(p) - 1) = '\0'; \ + if ( !*p ) /* skip empty lines */ \ + continue; \ + } \ + } + + /* + * List contents of tape. + */ + case 't': + setup(); + extractdirs(0); + initsymtable((char *)0); + printvolinfo(); + for (;;) { + NEXTFILE(p); + if (!p) + break; + canon(p, name, sizeof(name)); + ino = dirlookup(name); + if (ino == 0) + continue; + treescan(name, ino, listfile); + } + break; + /* + * Batch extraction of tape contents. + */ + case 'x': +#ifdef DEBUG_QFA + tistart = time(NULL); +#endif + setup(); + extractdirs(1); + initsymtable((char *)0); + for (;;) { + NEXTFILE(p); + if (!p) + break; + canon(p, name, sizeof(name)); + ino = dirlookup(name); + if (ino == 0) + continue; + if (mflag) + pathcheck(name); + treescan(name, ino, addfile); + } + createfiles(); + createlinks(); + setdirmodes(oflag ? FORCE : 0); + if (dflag) + checkrestore(); +#ifdef sunos + if (fdsmtc != -1) { + close(fdsmtc); + } +#endif /* sunos */ +#ifdef DEBUG_QFA + tiend = time(NULL); + titaken = tiend - tistart; + msg("restore took %d:%02d:%02d\n", titaken / 3600, + (titaken % 3600) / 60, titaken % 60); +#endif /* DEBUG_QFA */ + break; +#ifdef USE_QFA + case 'P': +#ifdef DEBUG_QFA + tistart = time(NULL); +#endif +#ifdef sunos + if (GetSCSIIDFromPath(inputdev, &scsiid)) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + if (scsiid < 0) { + errx(1, "can't get SCSI-ID for %s\n", inputdev); + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + errx(1, "can't open smtc device: %s, %d\n", smtcpath, errno); + } +#endif /* sunos */ + setup(); + msg("writing QFA positions to %s\n", gTapeposfile); + (void) umask(orig_umask); + if ((gTapeposfd = open(gTapeposfile, O_WRONLY|O_CREAT|O_TRUNC, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP + |S_IROTH|S_IWOTH)) < 0) + errx(1, "can't create tapeposfile\n"); + (void) umask(FORCED_UMASK); + /* print QFA-file header */ + sprintf(gTps, "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) + errx(1, "can't write tapeposfile\n"); + sprintf(gTps, "ino\ttapeno\ttapepos\n"); + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) + errx(1, "can't write tapeposfile\n"); + + extractdirs(1); + initsymtable((char *)0); + for (;;) { + NEXTFILE(p); + if (!p) + break; + canon(p, name, sizeof(name)); + ino = dirlookup(name); + if (ino == 0) + continue; + if (mflag) + pathcheck(name); + treescan(name, ino, addfile); + } + createfiles(); +#ifdef sunos + if (fdsmtc != -1) { + close(fdsmtc); + } +#endif /* sunos */ +#ifdef DEBUG_QFA + tiend = time(NULL); + titaken = tiend - tistart; + msg("writing QFA positions took %d:%02d:%02d\n", titaken / 3600, + (titaken % 3600) / 60, titaken % 60); +#endif /* DEBUG_QFA */ + break; +#endif /* USE_QFA */ + } + exit(0); + /* NOTREACHED */ + return 0; /* gcc shut up */ +} + +static void +usage(void) +{ + char white[MAXPATHLEN]; + const char *ext2ver, *ext2date; + + memset(white, ' ', MAXPATHLEN); + white[MIN(strlen(__progname), MAXPATHLEN - 1)] = '\0'; + +#ifdef __linux__ + ext2fs_get_library_version(&ext2ver, &ext2date); + (void)fprintf(stderr, "%s %s (using libext2fs %s of %s)\n", + __progname, _DUMP_VERSION, ext2ver, ext2date); +#else + (void)fprintf(stderr, "%s %s\n", __progname, _DUMP_VERSION); +#endif + +#ifdef KERBEROS +#define kerbflag "k" +#else +#define kerbflag +#endif + +#ifdef USE_QFA +#define qfaflag "[-Q file] " +#else +#define qfaflag +#endif + + fprintf(stderr, + "usage:" + "\t%s -C [-cd" kerbflag "lMvVy] [-b blocksize] [-D filesystem] [-f file]\n" + "\t%s [-F script] [-L limit] [-s fileno]\n" + "\t%s -i [-acdh" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n" + "\t%s [-F script] " qfaflag "[-s fileno]\n" +#ifdef USE_QFA + "\t%s -P file [-acdh" kerbflag "lmMuvVy] [-A file] [-b blocksize]\n" + "\t%s [-f file] [-F script] [-s fileno] [-X filelist] [file ...]\n" +#endif + "\t%s -r [-cd" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n" + "\t%s [-s fileno] [-T directory]\n" + "\t%s -R [-cd" kerbflag "lMuvVy] [-b blocksize] [-f file] [-F script]\n" + "\t%s [-s fileno] [-T directory]\n" + "\t%s -t [-cdh" kerbflag "lMuvVy] [-A file] [-b blocksize] [-f file]\n" + "\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n" + "\t%s -x [-acdh" kerbflag "lmMouvVy] [-A file] [-b blocksize] [-f file]\n" + "\t%s [-F script] " qfaflag "[-s fileno] [-X filelist] [file ...]\n", + __progname, white, + __progname, white, +#ifdef USE_QFA + __progname, white, +#endif + __progname, white, + __progname, white, + __progname, white, + __progname, white); + exit(1); +} + +/* + * obsolete -- + * Change set of key letters and ordered arguments into something + * getopt(3) will like. + */ +static void +obsolete(int *argcp, char **argvp[]) +{ + int argc, flags; + char *ap, **argv, *flagsp = NULL, **nargv, *p = NULL; + + /* Setup. */ + argv = *argvp; + argc = *argcp; + + /* Return if no arguments or first argument has leading dash. */ + ap = argv[1]; + if (argc == 1 || *ap == '-') + return; + + /* Allocate space for new arguments. */ + if ((*argvp = nargv = malloc((argc + 1) * sizeof(char *))) == NULL || + (p = flagsp = malloc(strlen(ap) + 2)) == NULL) + err(1, "malloc args"); + + *nargv++ = *argv; + argv += 2, argc -= 2; + + for (flags = 0; *ap; ++ap) { + switch (*ap) { + case 'A': + case 'b': + case 'D': + case 'f': + case 'F': + case 'L': + case 'Q': + case 's': + case 'T': + case 'X': + if (*argv == NULL) { + warnx("option requires an argument -- %c", *ap); + usage(); + } + if ((nargv[0] = malloc(strlen(*argv) + 2 + 1)) == NULL) + err(1, "malloc arg"); + nargv[0][0] = '-'; + nargv[0][1] = *ap; + (void)strcpy(&nargv[0][2], *argv); + ++argv; + ++nargv; + break; + default: + if (!flags) { + *p++ = '-'; + flags = 1; + } + *p++ = *ap; + break; + } + } + + /* Terminate flags. */ + if (flags) { + *p = '\0'; + *nargv++ = flagsp; + } + + /* Copy remaining arguments. */ + while ((*nargv++ = *argv++)); + + /* Update argument count. */ + *argcp = nargv - *argvp - 1; +} + +/* + * use_stdin -- + * reserve stdin for opt (avoid conflicts) + */ +void +use_stdin(const char *opt) +{ + if (stdin_opt) + errx(1, "can't handle standard input for both %s and %s", + stdin_opt, opt); + stdin_opt = opt; +} diff --git a/restore/restore.8.in b/restore/restore.8.in new file mode 100644 index 0000000..d7f934b --- /dev/null +++ b/restore/restore.8.in @@ -0,0 +1,757 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: restore.8.in,v 1.31 2003/06/11 13:01:36 stelian Exp $ +.\" +.TH RESTORE 8 "version __VERSION__ of __DATE__" BSD "System management commands" +.SH NAME +restore \- restore files or file systems from backups made with dump +.SH SYNOPSIS +.B restore \-C +[\fB\-cdklMvVy\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-D \fIfilesystem\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-L \fIlimit\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +.PP +.B restore \-i +[\fB\-acdhklmMNouvVy\fR] +[\fB\-A \fIfile\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-Q \fIfile\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +.PP +.B restore \-P +.I file +[\fB\-acdhklmMNuvVy\fR] +[\fB\-A \fIfile\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +[\fB\-X \fIfilelist\fR] +[ \fIfile ... \fR] +.PP +.B restore \-R +[\fB\-cdklMNuvVy\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +.PP +.B restore \-r +[\fB\-cdklMNuvVy\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +.PP +.B restore \-t +[\fB\-cdhklMNuvVy\fR] +[\fB\-A \fIfile\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-Q \fIfile\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +[\fB\-X \fIfilelist\fR] +[ \fIfile ... \fR] +.PP +.B restore \-x +[\fB\-adchklmMNouvVy\fR] +[\fB\-A \fIfile\fR] +[\fB\-b \fIblocksize\fR] +[\fB\-f \fIfile\fR] +[\fB\-F \fIscript\fR] +[\fB\-Q \fIfile\fR] +[\fB\-s \fIfileno\fR] +[\fB\-T \fIdirectory\fR] +[\fB\-X \fIfilelist\fR] +[ \fIfile ... \fR] +.PP +(The 4.3BSD option syntax is implemented for backward compatibility but is not +documented here.) +.SH DESCRIPTION +The +.B restore +command performs the inverse function of +.BR dump (8). +A full backup of a file system may be restored and subsequent incremental +backups layered on top of it. Single files and directory subtrees may be +restored from full or partial backups. +.B Restore +works across a network; to do this see the +.B \-f +flag described below. Other arguments to the command are file or directory +names specifying the files that are to be restored. Unless the +.B \-h +flag is specified (see below), the appearance of a directory name refers to +the files and (recursively) subdirectories of that directory. +.PP +Exactly one of the following flags is required: +.TP +.B \-C +This mode allows comparison of files from a dump. +.B Restore +reads the backup and compares its contents with files present on the disk. It +first changes its working directory to the root of the filesystem that was +dumped and compares the tape with the files in its new current directory. See +also the +.B \-L +flag described below. +.TP +.B \-i +This mode allows interactive restoration of files from a dump. After reading in +the directory information from the dump, +.B restore +provides a shell like interface that allows the user to move around the +directory tree selecting files to be extracted. The available commands are +given below; for those commands that require an argument, the default is the +current directory. +.RS +.TP +.B add \fR[\fIarg\fR] +The current directory or specified argument is added to the list of files to be +extracted. If a directory is specified, then it and all its descendents are +added to the extraction list (unless the +.B \-h +flag is specified on the command line). Files that are on the extraction list +are prepended with a \*(lq*\*(rq when they are listed by +.BR ls . +.TP +.BI cd " arg" +Change the current working directory to the specified argument. +.TP +.B delete \fR[\fIarg\fR] +The current directory or specified argument is deleted from the list of files +to be extracted. If a directory is specified, then it and all its descendents +are deleted from the extraction list (unless the +.B \-h +flag is specified on the command line). The most expedient way to extract most +of the files from a directory is to add the directory to the extraction list +and then delete those files that are not needed. +.TP +.B extract +All files on the extraction list are extracted from the dump. +.B Restore +will ask which volume the user wishes to mount. The fastest way to extract a f +ew files is to start with the last volume and work towards the first volume. +.TP +.B help +List a summary of the available commands. +.TP +.B ls \fR[\fIarg\fR] +List the current or specified directory. Entries that are directories are +appended with a \*(lq/\*(rq. Entries that have been marked for extraction are +prepended with a \*(lq*\*(rq. If the verbose flag is set, the inode number of +each entry is also listed. +.TP +.B pwd +Print the full pathname of the current working directory. +.TP +.B quit +.B Restore +immediately exits, even if the extraction list is not empty. +.TP +.B setmodes +All directories that have been added to the extraction list have their owner, +modes, and times set; nothing is extracted from the dump. This is useful for +cleaning up after a +.B restore +has been prematurely aborted. +.TP +.B verbose +The sense of the +.B \-v +flag is toggled. When set, the verbose flag causes the +.B ls +command to list the inode numbers of all entries. It also causes +.B restore +to print out information about each file as it is extracted. +.RE +.TP +.BI \-P " file" +.B Restore +creates a new Quick File Access file +.I file +from an existing dump file without restoring its contents. +.TP +.B \-R +.B Restore +requests a particular tape of a multi-volume set on which to restart a full +restore (see the +.B \-r +flag below). This is useful if the restore has been interrupted. +.TP +.B \-r +Restore (rebuild) a file system. The target file system should be made pristine +with +.BR mke2fs (8), +mounted, and the user +.BR cd 'd +into the pristine file system before starting the restoration of the initial +level 0 backup. If the level 0 restores successfully, the +.B \-r +flag may be used to restore any necessary incremental backups on top of the +level 0. The +.B \-r +flag precludes an interactive file extraction and can be detrimental to one's +health (not to mention the disk) if not used carefully. An example: +.IP +.RS 14 +.B mke2fs /dev/sda1 +.TP +.B mount /dev/sda1 /mnt +.TP +.B cd /mnt +.TP +.B restore rf /dev/st0 +.RE +.IP +Note that +.B restore +leaves a file +.I restoresymtable +in the root directory to pass information between incremental restore passes. +This file should be removed when the last incremental has been restored. +.IP +.BR Restore , +in conjunction with +.BR mke2fs (8) +and +.BR dump (8), +may be used to modify file system parameters such as size or block size. +.TP +.B \-t +The names of the specified files are listed if they occur on the backup. If no +file argument is given, the root directory is listed, which results in the +entire content of the backup being listed, unless the +.B \-h +flag has been specified. Note that the +.B \-t +flag replaces the function of the old +.BR dumpdir (8) +program. See also the +.B \-X +option below. +.TP +.B \-x +The named files are read from the given media. If a named file matches a +directory whose contents are on the backup and the +.B \-h +flag is not specified, the directory is recursively extracted. The owner, +modification time, and mode are restored (if possible). If no file argument is +given, the root directory is extracted, which results in the entire content of +the backup being extracted, unless the +.B \-h +flag has been specified. See also the +.B \-X +option below. +.SH OPTIONS +The following additional options may be specified: +.TP +.B \-a +In +.B \-i +or +.B \-x +mode, +.B restore +does ask the user for the volume number on which the files to be extracted are +supposed to be (in order to minimise the time by reading only the interesting +volumes). The +.B \-a +option disables this behaviour and reads all the volumes starting with 1. This +option is useful when the operator does not know on which volume the files to +be extracted are and/or when he prefers the longer unattended mode rather than +the shorter interactive mode. +.TP +.BI \-A " archive_file" +Read the table of contents from +.I archive_file +instead of the media. This option can be used in combination with the +.BR \-t , +.BR \-i , +or +.B \-x +options, making it possible to check whether files are on the media without +having to mount the media. +.TP +.BI \-b " blocksize" +The number of kilobytes per dump record. If the +.B \-b +option is not specified, +.B restore +tries to determine the media block size dynamically. +.TP +.B \-c +Normally, +.B restore +will try to determine dynamically whether the dump was made from an old +(pre-4.4) or new format file system. The +.B \-c +flag disables this check, and only allows reading a dump in the old format. +.TP +.B \-d +The +.B \-d +(debug) flag causes +.B restore +to print debug information. +.TP +.BI \-D " filesystem" +The +.B \-D +flag allows the user to specify the filesystem name when using +.B restore +with the +.B \-C +option to check the backup. +.TP +.BI \-f " file" +Read the backup from +.IR file ; +.I file +may be a special device file like +.I /dev/st0 +(a tape drive), +.I /dev/sda1 +(a disk drive), an ordinary file, or +.I \- +(the standard input). If the name of the file is of the form +.I host:file +or +.IR user@host:file , +.B restore +reads from the named file on the remote host using +.BR rmt (8). +.TP +.BI \-F " script" +Run script at the beginning of each tape. The device name and the current +volume number are passed on the command line. The script must return 0 if +.B restore +should continue without asking the user to change the tape, 1 if +.B restore +should continue but ask the user to change the tape. Any other exit code will +cause +.B restore +to abort. For security reasons, +.B restore +reverts back to the real user ID and the real group ID before running the +script. +.TP +.B \-h +Extract the actual directory, rather than the files that it references. This +prevents hierarchical restoration of complete subtrees from the dump. +.TP +.B \-k +Use Kerberos authentication when contacting the remote tape server. (Only +available if this options was enabled when +.B restore +was compiled.) +.TP +.B \-l +When doing remote restores, assume the remote file is a regular file (instead +of a tape device). If you're restoring a remote compressed file, you will need +to specify this option or +.B restore +will fail to access it correctly. +.TP +.BI \-L " limit" +The +.B \-L +flag allows the user to specify a maximal number of miscompares when using +.B restore +with the +.B \-C +option to check the backup. If this limit is reached, +.B restore +will abort with an error message. A value of 0 (the default value) disables +the check. +.TP +.B \-m +Extract by inode numbers rather than by file name. This is useful if only a few +files are being extracted, and one wants to avoid regenerating the complete +pathname to the file. +.TP +.B \-M +Enables the multi-volume feature (for reading dumps made using the +.B \-M +option of dump). The name specified with +.B \-f +is treated as a prefix and +.B restore +tries to read in sequence from +.I 001, 002 +etc. +.TP +.B \-N +The +.B \-N +flag causes +.B restore +to perform a full execution as requested by one of +.BR \-i , +.BR \-R , +.BR \-r , +.B t +or +.B x +command without actually writing any file on disk. +.TP +.B \-o +The +.B \-o +flag causes +.B restore +to automatically restore the current directory permissions without asking the +operator whether to do so in one of +.B \-i +or +.B \-x +modes. +.TP +.BI \-Q " file" +Use the file +.I file +in order to read tape position as stored using the dump Quick File Access mode, +in one of +.BR \-i , +.B \-x +or +.B \-t +mode. +.IP +It is recommended to set up the st driver to return logical tape positions +rather than physical before calling +.B dump/restore +with parameter +.BR \-Q . +Since not all tape devices support physical tape positions those tape devices +return an error during +.B dump/restore +when the st driver is set to the default physical setting. Please see the +.BR st (4) +man page, option +.B MTSETDRVBUFFER +, or the +.BR mt(1) +man page, on how to set the driver to return logical tape positions. +.IP +Before calling +.B restore +with parameter +.BR \-Q , +always make sure the st driver is set to return the same type of tape position +used during the call to +.BR dump . +Otherwise +.B restore +may be confused. +.IP +This option can be used when restoring from local or remote tapes (see above) +or from local or remote files. +.TP +.BI \-s " fileno" +Read from the specified +.I fileno +on a multi-file tape. File numbering starts at 1. +.TP +.BI \-T " directory" +The +.B \-T +flag allows the user to specify a directory to use for the storage of temporary +files. The default value is +.IR /tmp . +This flag is most useful when restoring files after having booted from a +floppy. There might be little or no space on the floppy filesystem, but another +source of space might exist. +.TP +.B \-u +When creating certain types of files, +.B restore +may generate a warning diagnostic if they already exist in the target +directory. To prevent this, the +.B \-u +(unlink) flag causes +.B restore +to remove old entries before attempting to create new ones. +.TP +.B \-v +Normally +.B restore +does its work silently. The +.B \-v +(verbose) flag causes it to type the name of each file it treats preceded by +its file type. +.TP +.B \-V +Enables reading multi-volume non-tape mediums like CDROMs. +.TP +.BI \-X " filelist" +Read list of files to be listed or extracted from the text file +.I filelist +in addition to those specified on the command line. This can be used in +conjunction with the +.B \-t +or +.B \-x +commands. The file +.I filelist +should contain file names separated by newlines. +.I filelist +may be an ordinary file or +.I - +(the standard input). +.TP +.B \-y +Do not ask the user whether to abort the restore in the event of an error. +Always try to skip over the bad block(s) and continue. +.SH DIAGNOSTICS +Complains if it gets a read error. If +.B y +has been specified, or the user responds +.BR y , +.B restore +will attempt to continue the restore. +.PP +If a backup was made using more than one tape volume, +.B restore +will notify the user when it is time to mount the next volume. If the +.B \-x +or +.B \-i +flag has been specified, +.B restore +will also ask which volume the user wishes to mount. The fastest way to extract +a few files is to start with the last volume, and work towards the first volume. +.PP +There are numerous consistency checks that can be listed by +.BR restore . +Most checks are self-explanatory or can \*(lqnever happen\*(rq. Common errors +are given below: +.TP +.I Converting to new file system format +A dump tape created from the old file system has been loaded. It is +automatically converted to the new file system format. +.TP +.I : not found on tape +The specified file name was listed in the tape directory, but was not found on +the tape. This is caused by tape read errors while looking for the file, and +from using a dump tape created on an active file system. +.TP +.I expected next file , got +A file that was not listed in the directory showed up. This can occur when +using a dump created on an active file system. +.TP +.I Incremental dump too low +When doing an incremental restore, a dump that was written before the previous +incremental dump, or that has too low an incremental level has been loaded. +.TP +.I Incremental dump too high +When doing an incremental restore, a dump that does not begin its coverage +where the previous incremental dump left off, or that has too high an +incremental level has been loaded. +.TP +.I Tape read error while restoring +.TP +.I Tape read error while skipping over inode +.TP +.I Tape read error while trying to resynchronize +A tape (or other media) read error has occurred. If a file name is specified, +its contents are probably partially wrong. If an inode is being skipped or the +tape is trying to resynchronize, no extracted files have been corrupted, though +files may not be found on the tape. +.TP +.I resync restore, skipped blocks +After a dump read error, +.B restore +may have to resynchronize itself. This message lists the number of blocks that +were skipped over. +.SH EXIT STATUS +.B Restore +exits with zero status on success. Tape errors are indicated with an exit code +of 1. +.PP +When doing a comparison of files from a dump, an exit code of 2 indicates that +some files were modified or deleted since the dump was made. +.SH ENVIRONMENT +If the following environment variable exists it will be utilized by +.BR restore : +.TP +.B TAPE +If no +.B \-f +option was specified, +.B restore +will use the device specified via +.B TAPE +as the dump device. +.B TAPE +may be of the form +.IR tapename , +.I host:tapename +or +.IR user@host:tapename . +.TP +.B TMPDIR +The directory given in +.B TMPDIR +will be used instead of +.I /tmp +to store temporary files. +.TP +.B RMT +The environment variable +.B RMT +will be used to determine the pathname of the remote +.BR rmt (8) +program. +.TP +.B RSH +.B Restore +uses the contents of this variable to determine the name of the remote shell +command to use when doing a network restore (rsh, ssh etc.). If this variable +is not set, +.BR rcmd (3) +will be used, but only root will be able to do a network restore. +.SH FILES +.TP +.I /dev/st0 +the default tape drive +.TP +.I /tmp/rstdir* +file containing directories on the tape +.TP +.I /tmp/rstmode* +owner, mode, and time stamps for directories +.TP +.I ./restoresymtable +information passed between incremental restores +.SH SEE ALSO +.BR dump (8), +.BR mount (8), +.BR mke2fs (8), +.BR rmt (8) +.SH BUGS +.B Restore +can get confused when doing incremental restores from dumps that were made on +active file systems. +.PP +A level 0 dump must be done after a full restore. Because +.B restore +runs in user code, it has no control over inode allocation; thus a full dump +must be done to get a new set of directories reflecting the new inode +numbering, even though the content of the files is unchanged. +.PP +The temporary files +.I /tmp/rstdir* +and +.I /tmp/rstmode* +are generated with a unique name based on the date of the dump and the process +ID (see +.BR mktemp (3) ), +except when +.B \-r +or +.B \-R +is used. Because +.B \-R +allows you to restart a +.B \-r +operation that may have been interrupted, the temporary files should be the +same across different processes. In all other cases, the files are unique +because it is possible to have two different dumps started at the same time, +and separate operations shouldn't conflict with each other. +.PP +To do a network restore, you have to run +.B restore +as root or use a remote shell replacement (see +.B RSH +variable). This is due to the previous security history of +.B dump +and +.BR restore . +( +.B restore +is written to be setuid root, but we are not certain all bugs are gone from the +code - run setuid at your own risk.) +.PP +At the end of restores in +.B \-i +or +.B \-x +modes (unless +.B \-o +option is in use), +.B restore +will ask the operator whether to set the permissions on the current +directory. If the operator confirms this action, the permissions +on the directory from where +.B restore +was launched will be replaced by the permissions on the dumped root +inode. Although this behaviour is not really a bug, it has proven itself +to be confusing for many users, so it is recommended to answer 'no', +unless you're performing a full restore and you do want to restore the +permissions on '/'. +.PP +It should be underlined that because it runs in user code, +.B restore +, when run with the +.B \-C +option, sees the files as the kernel presents them, whereas +.B dump +sees all the files on a given filesystem. In particular, this +can cause some confusion when comparing a dumped filesystem a part +of which is hidden by a filesystem mounted on top of it. +.SH AUTHOR +The +.B dump/restore +backup suite was ported to Linux's Second Extended File System by Remy Card +. He maintained the initial versions of +.B dump +(up and including 0.4b4, released in january 1997). +.PP +Starting with 0.4b5, the new maintainer is Stelian Pop . +.SH AVAILABILITY +The +.B dump/restore +backup suite is available from +.SH HISTORY +The +.B restore +command appeared in 4.2BSD. diff --git a/restore/restore.c b/restore/restore.c new file mode 100644 index 0000000..b95e356 --- /dev/null +++ b/restore/restore.c @@ -0,0 +1,1209 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: restore.c,v 1.33 2003/11/22 16:52:16 stelian Exp $"; +#endif /* not lint */ + +#include +#include + +#ifdef __linux__ +#include +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#else +#include +#endif +#endif /* __linux__ */ + +#include + +#include +#include +#include +#include + +#ifdef __linux__ +#include +#endif + +#include "restore.h" +#include "extern.h" + +static char *keyval __P((int)); + +/* + * This implements the 't' option. + * List entries on the tape. + */ +long +listfile(char *name, dump_ino_t ino, int type) +{ + long descend = hflag ? GOOD : FAIL; +#ifdef USE_QFA + long tnum; + long long tpos; +#endif + + if (TSTINO(ino, dumpmap) == 0) + return (descend); + Vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir "); +#ifdef USE_QFA + if (tapeposflag) { /* add QFA positions to output */ + (void)Inode2Tapepos(ino, &tnum, &tpos, 1); + fprintf(stdout, "%10lu\t%ld\t%lld\t%s\n", (unsigned long)ino, + tnum, tpos, name); + } + else +#endif + fprintf(stdout, "%10lu\t%s\n", (unsigned long)ino, name); + return (descend); +} + +/* + * This implements the 'x' option. + * Request that new entries be extracted. + */ +long +addfile(char *name, dump_ino_t ino, int type) +{ + struct entry *ep, *np; + long descend = hflag ? GOOD : FAIL; + char buf[100]; + + if (TSTINO(ino, dumpmap) == 0) { + Dprintf(stdout, "%s: not on the tape\n", name); + return (descend); + } + if (ino == WINO && command == 'i' && !vflag) + return (descend); + if (!mflag) { + (void) snprintf(buf, sizeof(buf), "./%lu", (unsigned long)ino); + name = buf; + if (type == NODE) { + (void) genliteraldir(name, ino); + return (descend); + } + } + ep = lookupino(ino); + if (ep != NULL) { + if (strcmp(name, myname(ep)) == 0) { + ep->e_flags |= NEW; + return (descend); + } + type |= LINK; + for (np = ep->e_links; np; np = np->e_links) + if (strcmp(name, myname(np)) == 0) { + np->e_flags |= NEW; + return (descend); + } + } + ep = addentry(name, ino, type); +#ifdef USE_QFA + if ((type == NODE) && (!createtapeposflag)) +#else + if (type == NODE) +#endif + newnode(ep); + ep->e_flags |= NEW; + return (descend); +} + +/* + * This is used by the 'i' option to undo previous requests made by addfile. + * Delete entries from the request queue. + */ +/* ARGSUSED */ +long +deletefile(char *name, dump_ino_t ino, UNUSED(int type)) +{ + long descend = hflag ? GOOD : FAIL; + struct entry *ep; + + if (TSTINO(ino, dumpmap) == 0) + return (descend); + ep = lookupname(name); + if (ep != NULL) { + ep->e_flags &= ~NEW; + ep->e_flags |= REMOVED; + if (ep->e_type != NODE) + freeentry(ep); + } + return (descend); +} + +/* + * The following four routines implement the incremental + * restore algorithm. The first removes old entries, the second + * does renames and calculates the extraction list, the third + * cleans up link names missed by the first two, and the final + * one deletes old directories. + * + * Directories cannot be immediately deleted, as they may have + * other files in them which need to be moved out first. As + * directories to be deleted are found, they are put on the + * following deletion list. After all deletions and renames + * are done, this list is actually deleted. + */ +static struct entry *removelist; + +/* + * Remove invalid whiteouts from the old tree. + * Remove unneeded leaves from the old tree. + * Remove directories from the lookup chains. + */ +void +removeoldleaves(void) +{ + struct entry *ep, *nextep; + dump_ino_t i, mydirino; + + Vprintf(stdout, "Mark entries to be removed.\n"); + if ((ep = lookupino(WINO))) { + Vprintf(stdout, "Delete whiteouts\n"); + for ( ; ep != NULL; ep = nextep) { + nextep = ep->e_links; + mydirino = ep->e_parent->e_ino; + /* + * We remove all whiteouts that are in directories + * that have been removed or that have been dumped. + */ + if (TSTINO(mydirino, usedinomap) && + !TSTINO(mydirino, dumpmap)) + continue; +#ifdef __linux__ + (void)fprintf(stderr, "BUG! Should call delwhiteout\n"); +#else +#ifdef sunos +#else + delwhiteout(ep); +#endif +#endif + freeentry(ep); + } + } + for (i = ROOTINO + 1; i < maxino; i++) { + ep = lookupino(i); + if (ep == NULL) + continue; + if (TSTINO(i, usedinomap)) + continue; + for ( ; ep != NULL; ep = ep->e_links) { + Dprintf(stdout, "%s: REMOVE\n", myname(ep)); + if (ep->e_type == LEAF) { + removeleaf(ep); + freeentry(ep); + } else { + mktempname(ep); + deleteino(ep->e_ino); + ep->e_next = removelist; + removelist = ep; + } + } + } +} + +/* + * For each directory entry on the incremental tape, determine which + * category it falls into as follows: + * KEEP - entries that are to be left alone. + * NEW - new entries to be added. + * EXTRACT - files that must be updated with new contents. + * LINK - new links to be added. + * Renames are done at the same time. + */ +long +nodeupdates(char *name, dump_ino_t ino, int type) +{ + struct entry *ep, *np, *ip; + long descend = GOOD; + int lookuptype = 0; + int key = 0; + /* key values */ +# define ONTAPE 0x1 /* inode is on the tape */ +# define INOFND 0x2 /* inode already exists */ +# define NAMEFND 0x4 /* name already exists */ +# define MODECHG 0x8 /* mode of inode changed */ + + /* + * This routine is called once for each element in the + * directory hierarchy, with a full path name. + * The "type" value is incorrectly specified as LEAF for + * directories that are not on the dump tape. + * + * Check to see if the file is on the tape. + */ + if (TSTINO(ino, dumpmap)) + key |= ONTAPE; + /* + * Check to see if the name exists, and if the name is a link. + */ + np = lookupname(name); + if (np != NULL) { + key |= NAMEFND; + ip = lookupino(np->e_ino); + if (ip == NULL) + panic("corrupted symbol table\n"); + if (ip != np) + lookuptype = LINK; + } + /* + * Check to see if the inode exists, and if one of its links + * corresponds to the name (if one was found). + */ + ip = lookupino(ino); + if (ip != NULL) { + key |= INOFND; + for (ep = ip->e_links; ep != NULL; ep = ep->e_links) { + if (ep == np) { + ip = ep; + break; + } + } + } + /* + * If both a name and an inode are found, but they do not + * correspond to the same file, then both the inode that has + * been found and the inode corresponding to the name that + * has been found need to be renamed. The current pathname + * is the new name for the inode that has been found. Since + * all files to be deleted have already been removed, the + * named file is either a now unneeded link, or it must live + * under a new name in this dump level. If it is a link, it + * can be removed. If it is not a link, it is given a + * temporary name in anticipation that it will be renamed + * when it is later found by inode number. + */ + if (((key & (INOFND|NAMEFND)) == (INOFND|NAMEFND)) && ip != np) { + if (lookuptype == LINK) { + removeleaf(np); + freeentry(np); + } else { + Dprintf(stdout, "name/inode conflict, mktempname %s\n", + myname(np)); + mktempname(np); + } + np = NULL; + key &= ~NAMEFND; + } + if ((key & ONTAPE) && + (((key & INOFND) && ip->e_type != type) || + ((key & NAMEFND) && np->e_type != type))) + key |= MODECHG; + + /* + * Decide on the disposition of the file based on its flags. + * Note that we have already handled the case in which + * a name and inode are found that correspond to different files. + * Thus if both NAMEFND and INOFND are set then ip == np. + */ + switch (key) { + + /* + * A previously existing file has been found. + * Mark it as KEEP so that other links to the inode can be + * detected, and so that it will not be reclaimed by the search + * for unreferenced names. + */ + case INOFND|NAMEFND: + ip->e_flags |= KEEP; + Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, + flagvalues(ip)); + break; + + /* + * A file on the tape has a name which is the same as a name + * corresponding to a different file in the previous dump. + * Since all files to be deleted have already been removed, + * this file is either a now unneeded link, or it must live + * under a new name in this dump level. If it is a link, it + * can simply be removed. If it is not a link, it is given a + * temporary name in anticipation that it will be renamed + * when it is later found by inode number (see INOFND case + * below). The entry is then treated as a new file. + */ + case ONTAPE|NAMEFND: + case ONTAPE|NAMEFND|MODECHG: + if (lookuptype == LINK) { + removeleaf(np); + freeentry(np); + } else { + mktempname(np); + } + /* fall through */ + + /* + * A previously non-existent file. + * Add it to the file system, and request its extraction. + * If it is a directory, create it immediately. + * (Since the name is unused there can be no conflict) + */ + case ONTAPE: + ep = addentry(name, ino, type); + if (type == NODE) + newnode(ep); + ep->e_flags |= NEW|KEEP; + Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, + flagvalues(ep)); + break; + + /* + * A file with the same inode number, but a different + * name has been found. If the other name has not already + * been found (indicated by the KEEP flag, see above) then + * this must be a new name for the file, and it is renamed. + * If the other name has been found then this must be a + * link to the file. Hard links to directories are not + * permitted, and are either deleted or converted to + * symbolic links. Finally, if the file is on the tape, + * a request is made to extract it. + */ + case ONTAPE|INOFND: + if (type == LEAF && (ip->e_flags & KEEP) == 0) + ip->e_flags |= EXTRACT; + /* fall through */ + case INOFND: + if ((ip->e_flags & KEEP) == 0) { + renameit(myname(ip), name); + moveentry(ip, name); + ip->e_flags |= KEEP; + Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, + flagvalues(ip)); + break; + } + if (ip->e_type == NODE) { + descend = FAIL; + fprintf(stderr, + "deleted hard link %s to directory %s\n", + name, myname(ip)); + break; + } + ep = addentry(name, ino, type|LINK); + ep->e_flags |= NEW; + Dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name, + flagvalues(ep)); + break; + + /* + * A previously known file which is to be updated. If it is a link, + * then all names referring to the previous file must be removed + * so that the subset of them that remain can be recreated. + */ + case ONTAPE|INOFND|NAMEFND: + if (lookuptype == LINK) { + removeleaf(np); + freeentry(np); + ep = addentry(name, ino, type|LINK); + if (type == NODE) + newnode(ep); + ep->e_flags |= NEW|KEEP; + Dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name, + flagvalues(ep)); + break; + } + if (type == LEAF && lookuptype != LINK) + np->e_flags |= EXTRACT; + np->e_flags |= KEEP; + Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, + flagvalues(np)); + break; + + /* + * An inode is being reused in a completely different way. + * Normally an extract can simply do an "unlink" followed + * by a "creat". Here we must do effectively the same + * thing. The complications arise because we cannot really + * delete a directory since it may still contain files + * that we need to rename, so we delete it from the symbol + * table, and put it on the list to be deleted eventually. + * Conversely if a directory is to be created, it must be + * done immediately, rather than waiting until the + * extraction phase. + */ + case ONTAPE|INOFND|MODECHG: + case ONTAPE|INOFND|NAMEFND|MODECHG: + if (ip->e_flags & KEEP) { + badentry(ip, "cannot KEEP and change modes"); + break; + } + if (ip->e_type == LEAF) { + /* changing from leaf to node */ + for ( ; ip != NULL; ip = ip->e_links) { + if (ip->e_type != LEAF) + badentry(ip, "NODE and LEAF links to same inode"); + removeleaf(ip); + freeentry(ip); + } + ip = addentry(name, ino, type); + newnode(ip); + } else { + /* changing from node to leaf */ + if ((ip->e_flags & TMPNAME) == 0) + mktempname(ip); + deleteino(ip->e_ino); + ip->e_next = removelist; + removelist = ip; + ip = addentry(name, ino, type); + } + ip->e_flags |= NEW|KEEP; + Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name, + flagvalues(ip)); + break; + + /* + * A hard link to a directory that has been removed. + * Ignore it. + */ + case NAMEFND: + Dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key), + name); + descend = FAIL; + break; + + /* + * If we find a directory entry for a file that is not on + * the tape, then we must have found a file that was created + * while the dump was in progress. Since we have no contents + * for it, we discard the name knowing that it will be on the + * next incremental tape. + */ + case 0: + if (compare_ignore_not_found) break; + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + name, (unsigned long)ino); + do_compare_error; + break; + + /* + * If any of these arise, something is grievously wrong with + * the current state of the symbol table. + */ + case INOFND|NAMEFND|MODECHG: + case NAMEFND|MODECHG: + case INOFND|MODECHG: + fprintf(stderr, "[%s] %s: inconsistent state\n", keyval(key), + name); + break; + + /* + * These states "cannot" arise for any state of the symbol table. + */ + case ONTAPE|MODECHG: + case MODECHG: + default: + panic("[%s] %s: impossible state\n", keyval(key), name); + break; + } + return (descend); +} + +/* + * Calculate the active flags in a key. + */ +static char * +keyval(int key) +{ + static char keybuf[32]; + + (void) strcpy(keybuf, "|NIL"); + keybuf[0] = '\0'; + if (key & ONTAPE) + (void) strcat(keybuf, "|ONTAPE"); + if (key & INOFND) + (void) strcat(keybuf, "|INOFND"); + if (key & NAMEFND) + (void) strcat(keybuf, "|NAMEFND"); + if (key & MODECHG) + (void) strcat(keybuf, "|MODECHG"); + return (&keybuf[1]); +} + +/* + * Find unreferenced link names. + */ +void +findunreflinks(void) +{ + struct entry *ep, *np; + dump_ino_t i; + + Vprintf(stdout, "Find unreferenced names.\n"); + for (i = ROOTINO; i < maxino; i++) { + ep = lookupino(i); + if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0) + continue; + for (np = ep->e_entries; np != NULL; np = np->e_sibling) { + if (np->e_flags == 0) { + Dprintf(stdout, + "%s: remove unreferenced name\n", + myname(np)); + removeleaf(np); + freeentry(np); + } + } + } + /* + * Any leaves remaining in removed directories is unreferenced. + */ + for (ep = removelist; ep != NULL; ep = ep->e_next) { + for (np = ep->e_entries; np != NULL; np = np->e_sibling) { + if (np->e_type == LEAF) { + if (np->e_flags != 0) + badentry(np, "unreferenced with flags"); + Dprintf(stdout, + "%s: remove unreferenced name\n", + myname(np)); + removeleaf(np); + freeentry(np); + } + } + } +} + +/* + * Remove old nodes (directories). + * Note that this routine runs in O(N*D) where: + * N is the number of directory entries to be removed. + * D is the maximum depth of the tree. + * If N == D this can be quite slow. If the list were + * topologically sorted, the deletion could be done in + * time O(N). + */ +void +removeoldnodes(void) +{ + struct entry *ep, **prev; + long change; + + Vprintf(stdout, "Remove old nodes (directories).\n"); + do { + change = 0; + prev = &removelist; + for (ep = removelist; ep != NULL; ep = *prev) { + if (ep->e_entries != NULL) { + prev = &ep->e_next; + continue; + } + *prev = ep->e_next; + removenode(ep); + freeentry(ep); + change++; + } + } while (change); + for (ep = removelist; ep != NULL; ep = ep->e_next) + badentry(ep, "cannot remove, non-empty"); +} + +/* Compare the file specified in `ep' (which is on tape) to the */ +/* current copy of this file on disk. If do_compare is 0, then just */ +/* make our caller think we did it--this is used to handle hard links */ +/* to files and devices. */ +static void +compare_entry(struct entry *ep, int do_compare) +{ + if ((ep->e_flags & (NEW|EXTRACT)) == 0) { + badentry(ep, "unexpected file on tape"); + do_compare_error; + } + if (do_compare) (void) comparefile(myname(ep)); + ep->e_flags &= ~(NEW|EXTRACT); +} + +/* + * This is the routine used to compare files for the 'C' command. + */ +void +compareleaves(void) +{ + struct entry *ep; + dump_ino_t first; + long curvol; + + first = lowerbnd(ROOTINO); + curvol = volno; + while (curfile.ino < maxino) { + first = lowerbnd(first); + /* + * If the next available file is not the one which we + * expect then we have missed one or more files. Since + * we do not request files that were not on the tape, + * the lost files must have been due to a tape read error, + * or a file that was removed while the dump was in progress. + */ + while (first < curfile.ino) { + ep = lookupino(first); + if (ep == NULL) + panic("%d: bad first\n", first); + fprintf(stderr, "%s: not found on tape\n", myname(ep)); + do_compare_error; + ep->e_flags &= ~(NEW|EXTRACT); + first = lowerbnd(first); + } + /* + * If we find files on the tape that have no corresponding + * directory entries, then we must have found a file that + * was created while the dump was in progress. Since we have + * no name for it, we discard it knowing that it will be + * on the next incremental tape. + */ + if (first != curfile.ino) { + fprintf(stderr, "expected next file %ld, got %lu\n", + (long)first, (unsigned long)curfile.ino); + do_compare_error; + skipfile(); + goto next; + } + ep = lookupino(curfile.ino); + if (ep == NULL) { + panic("unknown file on tape\n"); + do_compare_error; + } + compare_entry(ep, 1); + for (ep = ep->e_links; ep != NULL; ep = ep->e_links) { + compare_entry(ep, 0); + } + + /* + * We checkpoint the restore after every tape reel, so + * as to simplify the amount of work re quired by the + * 'R' command. + */ + next: + if (curvol != volno) { + skipmaps(); + curvol = volno; + } + } + /* + * If we encounter the end of the tape and the next available + * file is not the one which we expect then we have missed one + * or more files. Since we do not request files that were not + * on the tape, the lost files must have been due to a tape + * read error, or a file that was removed while the dump was + * in progress. + */ + first = lowerbnd(first); + while (first < curfile.ino) { + ep = lookupino(first); + if (ep == NULL) + panic("%d: bad first\n", first); + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + myname(ep), (unsigned long)first); + do_compare_error; + ep->e_flags &= ~(NEW|EXTRACT); + first = lowerbnd(first); + } +} + +/* + * This is the routine used to extract files for the 'r' command. + * Extract new leaves. + */ +void +createleaves(char *symtabfile) +{ + struct entry *ep; + dump_ino_t first; + long curvol; + int doremove; + + if (command == 'R') { + Vprintf(stdout, "Continue extraction of new leaves\n"); + } else { + Vprintf(stdout, "Extract new leaves.\n"); + dumpsymtable(symtabfile, volno); + } + first = lowerbnd(ROOTINO); + curvol = volno; + while (curfile.ino < maxino) { + first = lowerbnd(first); + /* + * If the next available file is not the one which we + * expect then we have missed one or more files. Since + * we do not request files that were not on the tape, + * the lost files must have been due to a tape read error, + * or a file that was removed while the dump was in progress. + */ + while (first < curfile.ino) { + ep = lookupino(first); + if (ep == NULL) + panic("%d: bad first\n", first); + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + myname(ep), (unsigned long)first); + ep->e_flags &= ~(NEW|EXTRACT); + first = lowerbnd(first); + } + /* + * If we find files on the tape that have no corresponding + * directory entries, then we must have found a file that + * was created while the dump was in progress. Since we have + * no name for it, we discard it knowing that it will be + * on the next incremental tape. + */ + if (first != curfile.ino) { + fprintf(stderr, "expected next file %ld, got %lu\n", + (long)first, (unsigned long)curfile.ino); + skipfile(); + goto next; + } + ep = lookupino(curfile.ino); + if (ep == NULL) + panic("unknown file on tape\n"); + if ((ep->e_flags & (NEW|EXTRACT)) == 0) + badentry(ep, "unexpected file on tape"); + /* + * If the file is to be extracted, then the old file must + * be removed since its type may change from one leaf type + * to another (e.g. "file" to "character special"). + */ + if ((ep->e_flags & EXTRACT) != 0) + doremove = 1; + else + doremove = 0; + (void) extractfile(ep, doremove); + ep->e_flags &= ~(NEW|EXTRACT); + +finderres: + if ((first == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: +#ifdef DUMP_MACOSX + (void)extractfinderinfoufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_MACOSRESFORK: +#ifdef DUMP_MACOSX + (void)extractresourceufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_ACL: + msg("ACLs not supported in this version, skipping\n"); + skipfile(); + break; + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + goto finderres; + } + + /* + * We checkpoint the restore after every tape reel, so + * as to simplify the amount of work required by the + * 'R' command. + */ +next: + if (curvol != volno) { + dumpsymtable(symtabfile, volno); + skipmaps(); + curvol = volno; + } + } + /* + * If we encounter the end of the tape and the next available + * file is not the one which we expect then we have missed one + * or more files. Since we do not request files that were not + * on the tape, the lost files must have been due to a tape + * read error, or a file that was removed while the dump was + * in progress. + */ + first = lowerbnd(first); + while (first < curfile.ino) { + ep = lookupino(first); + if (ep == NULL) + panic("%d: bad first\n", first); + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + myname(ep), (unsigned long)first); + do_compare_error; + ep->e_flags &= ~(NEW|EXTRACT); + first = lowerbnd(first); + } +} + +/* + * This is the routine used to extract files for the 'x' and 'i' commands. + * Efficiently extract a subset of the files on a tape. + */ +void +createfiles(void) +{ + dump_ino_t first, next, last; + struct entry *ep; + long curvol; +#ifdef USE_QFA + long tnum, tmpcnt; + long long tpos, curtpos = 0; + time_t tistart, tiend, titaken; + int volChg; +#endif + + Vprintf(stdout, "Extract requested files\n"); + curfile.action = SKIP; +#ifdef USE_QFA + if (tapeposflag) + curfile.ino = 0; + else +#endif + if (volinfo[1] == ROOTINO) + curfile.ino = 0; + else + getvol((long)1); + skipmaps(); + skipdirs(); + first = lowerbnd(ROOTINO); + last = upperbnd(maxino - 1); + for (;;) { +#ifdef USE_QFA + tmpcnt = 1; +#endif + first = lowerbnd(first); + last = upperbnd(last); + /* + * Check to see if any files remain to be extracted + */ + if (first > last) + return; + /* + * Reject any volumes with inodes greater + * than the last one needed + */ + while (curfile.ino > last) { + curfile.action = SKIP; + if (!pipein) + getvol((long)0); + if (curfile.ino == maxino) { + next = lowerbnd(first); + while (next < curfile.ino) { + ep = lookupino(next); + if (ep == NULL) + panic("corrupted symbol table\n"); + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + myname(ep), (unsigned long)next); + ep->e_flags &= ~NEW; + next = lowerbnd(next); + } + return; + } + skipmaps(); + skipdirs(); + } + /* + * Decide on the next inode needed. + * Skip across the inodes until it is found + * or an out of order volume change is encountered + */ + next = lowerbnd(curfile.ino); +#ifdef USE_QFA + tistart = time(NULL); + if (tapeposflag) { + /* get tape position for inode */ + (void)Inode2Tapepos(next, &tnum, &tpos, 0); + if (tpos != 0) { + if (tnum != volno) { + (void)RequestVol(tnum); + volChg = 1; + } else { + volChg = 0; + } + if (GetTapePos(&curtpos) == 0) { + /* curtpos +1000 ???, some drives + * might be too slow */ + if (((tpos > (curtpos + 1000)) && (volChg == 0)) || ((tpos != curtpos) && (volChg == 1))) { + volChg = 0; +#ifdef DEBUG_QFA + msg("positioning tape %ld from %lld to %lld for inode %lu ...\n", volno, curtpos, tpos, (unsigned long)next); +#endif + if (GotoTapePos(tpos) == 0) { +#ifdef DEBUG_QFA + if (GetTapePos(&curtpos) == 0) { + msg("before resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } +#endif + ReReadInodeFromTape(next); +#ifdef DEBUG_QFA + if (GetTapePos(&curtpos) == 0) { + msg("after resnyc at tape position %lld (%ld, %ld, %s)\n", curtpos, next, curfile.ino, curfile.name); + } +#endif + } + } else { +#ifdef DEBUG_QFA + msg("already at tape %ld position %ld for inode %lu ...\n", volno, tpos, (unsigned long)next); +#endif + } + } + } + } + else +#endif /* USA_QFA */ + if (volinfo[1] == ROOTINO) { + int i, goodvol = 1; + + for (i = 1; i < (int)TP_NINOS && volinfo[i] != 0; ++i) + if (volinfo[i] < next) + goodvol = i; + + if (goodvol != volno) + RequestVol(goodvol); + } + + do { + curvol = volno; + while (next > curfile.ino && volno == curvol) { +#ifdef USE_QFA + ++tmpcnt; +#endif + skipfile(); + } + skipmaps(); + skipdirs(); + } while (volno == curvol + 1); +#ifdef USE_QFA + tiend = time(NULL); + titaken = tiend - tistart; +#ifdef DEBUG_QFA + if (titaken / 60 > 0) + msg("%ld reads took %d:%02d:%02d\n", + tmpcnt, titaken / 3600, + (titaken % 3600) / 60, titaken % 60); +#endif +#endif /* USE_QFA */ + + /* + * If volume change out of order occurred the + * current state must be recalculated + */ + if (volno != curvol) + continue; + /* + * If the current inode is greater than the one we were + * looking for then we missed the one we were looking for. + * Since we only attempt to extract files listed in the + * dump map, the lost files must have been due to a tape + * read error, or a file that was removed while the dump + * was in progress. Thus we report all requested files + * between the one we were looking for, and the one we + * found as missing, and delete their request flags. + */ + while (next < curfile.ino) { + ep = lookupino(next); + if (ep == NULL) + panic("corrupted symbol table\n"); +#ifdef USE_QFA + if (!createtapeposflag) +#endif + fprintf(stderr, "%s: (inode %lu) not found on tape\n", + myname(ep), (unsigned long)next); + ep->e_flags &= ~NEW; + next = lowerbnd(next); + } + /* + * The current inode is the one that we are looking for, + * so extract it per its requested name. + */ + if (next == curfile.ino && next <= last) { + ep = lookupino(next); + if (ep == NULL) + panic("corrupted symbol table\n"); +#ifdef USE_QFA + if (createtapeposflag) { +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %ld\n", curfile.ino, curtapepos); +#endif + sprintf(gTps, "%ld\t%ld\t%lld\n", (unsigned long)curfile.ino, volno, curtapepos); + if (write(gTapeposfd, gTps, strlen(gTps)) != (ssize_t)strlen(gTps)) + warn("error writing tapepos file.\n"); + skipfile(); + } else { +#endif /* USE_QFA */ + (void) extractfile(ep, 0); + +finderres: + if ((next == curfile.ino) && (spcl.c_flags & DR_EXTATTRIBUTES)) { + switch (spcl.c_extattributes) { + case EXT_MACOSFNDRINFO: +#ifdef DUMP_MACOSX + (void)extractfinderinfoufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_MACOSRESFORK: +#ifdef DUMP_MACOSX + (void)extractresourceufs(myname(ep)); +#else + msg("MacOSX not supported in this version, skipping\n"); + skipfile(); +#endif + break; + case EXT_ACL: + msg("ACLs not supported in this version, skipping\n"); + skipfile(); + break; + default: + msg("unexpected inode extension %ld, skipping\n", spcl.c_extattributes); + skipfile(); + break; + } + goto finderres; + } + +#ifdef USE_QFA + } +#endif /* USE_QFA */ + ep->e_flags &= ~NEW; + if (volno != curvol) + skipmaps(); + } + } +} + +/* + * Add links. + */ +void +createlinks(void) +{ + struct entry *np, *ep; + dump_ino_t i; + char name[BUFSIZ]; + + if ((ep = lookupino(WINO))) { + Vprintf(stdout, "Add whiteouts\n"); + for ( ; ep != NULL; ep = ep->e_links) { + if ((ep->e_flags & NEW) == 0) + continue; +#ifdef __linux__ + (void)fprintf(stderr, "BUG! Should call addwhiteout\n"); +#else +#ifdef sunos +#else + (void) addwhiteout(myname(ep)); +#endif +#endif + ep->e_flags &= ~NEW; + } + } + Vprintf(stdout, "Add links\n"); + for (i = ROOTINO; i < maxino; i++) { + ep = lookupino(i); + if (ep == NULL) + continue; + for (np = ep->e_links; np != NULL; np = np->e_links) { + if ((np->e_flags & NEW) == 0) + continue; + (void) strcpy(name, myname(ep)); + if (ep->e_type == NODE) { + (void) linkit(name, myname(np), SYMLINK); + } else { + (void) linkit(name, myname(np), HARDLINK); + } + np->e_flags &= ~NEW; + } + } +} + +/* + * Check the symbol table. + * We do this to insure that all the requested work was done, and + * that no temporary names remain. + */ +void +checkrestore(void) +{ + struct entry *ep; + dump_ino_t i; + + Vprintf(stdout, "Check the symbol table.\n"); + for (i = WINO; i < maxino; i++) { + for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { + ep->e_flags &= ~KEEP; + if (ep->e_type == NODE) + ep->e_flags &= ~(NEW|EXISTED); + if (ep->e_flags /* != NULL */) + badentry(ep, "incomplete operations"); + } + } +} + +/* + * Compare with the directory structure on the tape + * A paranoid check that things are as they should be. + */ +long +verifyfile(char *name, dump_ino_t ino, int type) +{ + struct entry *np, *ep; + long descend = GOOD; + + ep = lookupname(name); + if (ep == NULL) { + fprintf(stderr, "Warning: missing name %s\n", name); + return (FAIL); + } + np = lookupino(ino); + if (np != ep) + descend = FAIL; + for ( ; np != NULL; np = np->e_links) + if (np == ep) + break; + if (np == NULL) + panic("missing inumber %d\n", ino); + if (ep->e_type == LEAF && type != LEAF) + badentry(ep, "type should be LEAF"); + return (descend); +} diff --git a/restore/restore.h b/restore/restore.h new file mode 100644 index 0000000..bf6284b --- /dev/null +++ b/restore/restore.h @@ -0,0 +1,196 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + * + * $Id: restore.h,v 1.29 2004/04/13 13:04:33 stelian Exp $ + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +/* + * Flags + */ +extern int aflag; /* automatic volume increment */ +extern char *Afile; /* archive file */ +extern int cvtflag; /* convert from old to new tape format */ +extern int bflag; /* set input block size */ +extern int dflag; /* print out debugging info */ +extern int hflag; /* restore heirarchies */ +extern int lflag; /* assume remote filename is a regular file */ +extern int Lflag; /* compare errors limit */ +extern int mflag; /* restore by name instead of inode number */ +extern int Mflag; /* multi-volume restore */ +extern int oflag; /* do restore permissions without asking */ +extern int Vflag; /* multi-volume on a single device like CDROM */ +extern int Nflag; /* do not write the disk */ +extern int uflag; /* unlink symlink targets */ +extern int vflag; /* print out actions taken */ +extern int yflag; /* always try to recover from tape errors */ +extern int zflag; /* tape is in compressed format */ +extern int ufs2flag; /* tape is a FreeBSD UFS2 dump */ +extern char* bot_script; /* beginning of tape script */ +/* + * Global variables + */ +extern char *host; /* name of the remote host */ +extern char *dumpmap; /* map of inodes on this dump tape */ +extern char *usedinomap; /* map of inodes that are in use on this fs */ +extern dump_ino_t maxino; /* highest numbered inode in this file system */ +extern long dumpnum; /* location of the dump on this tape */ +extern long volno; /* current volume being read */ +extern long ntrec; /* number of TP_BSIZE records per tape block */ +extern time_t dumptime; /* time that this dump begins */ +extern time_t dumpdate; /* time that this dump was made */ +extern char command; /* opration being performed */ +extern FILE *terminal; /* file descriptor for the terminal input */ +extern int pipein; /* input is from a pipe */ +extern char *tmpdir; /* name of temp directory */ +extern int oldinofmt; /* reading tape with old format inodes */ +extern int Bcvt; /* need byte swapping on inodes and dirs */ +extern int compare_ignore_not_found; + /* used to compare incremental dumps, */ + /* so messages about "not found" files */ + /* isn't seen. */ +extern int compare_errors; /* did we encounter any compare errors? */ +extern char filesys[NAMELEN];/* name of dumped filesystem */ +extern dump_ino_t volinfo[]; /* which inode on which volume archive info */ + +/* + * Each file in the file system is described by one of these entries + */ +struct entry { + char *e_name; /* the current name of this entry */ + u_char e_namlen; /* length of this name */ + char e_type; /* type of this entry, see below */ + short e_flags; /* status flags, see below */ + dump_ino_t e_ino; /* inode number in previous file sys */ + long e_index; /* unique index (for dumpped table) */ + struct entry *e_parent; /* pointer to parent directory (..) */ + struct entry *e_sibling; /* next element in this directory (.) */ + struct entry *e_links; /* hard links to this inode */ + struct entry *e_entries; /* for directories, their entries */ + struct entry *e_next; /* hash chain list */ +}; +/* types */ +#define LEAF 1 /* non-directory entry */ +#define NODE 2 /* directory entry */ +#define LINK 4 /* synthesized type, stripped by addentry */ +/* flags */ +#define EXTRACT 0x0001 /* entry is to be replaced from the tape */ +#define NEW 0x0002 /* a new entry to be extracted */ +#define KEEP 0x0004 /* entry is not to change */ +#define REMOVED 0x0010 /* entry has been removed */ +#define TMPNAME 0x0020 /* entry has been given a temporary name */ +#define EXISTED 0x0040 /* directory already existed during extract */ + +/* + * Constants associated with entry structs + */ +#define HARDLINK 1 +#define SYMLINK 2 +#define TMPHDR "RSTTMP" + +/* + * The entry describes the next file available on the tape + */ +struct context { + char *name; /* name of file */ + dump_ino_t ino; /* inumber of file */ +#if defined(__linux__) || defined(sunos) + struct new_bsd_inode *dip; /* pointer to inode */ +#else + struct dinode *dip; /* pointer to inode */ +#endif + char action; /* action being taken on this file */ +} curfile; +/* actions */ +#define USING 1 /* extracting from the tape */ +#define SKIP 2 /* skipping */ +#define UNKNOWN 3 /* disposition or starting point is unknown */ + +/* + * Definitions for library routines operating on directories. + */ +typedef struct rstdirdesc RST_DIR; + +/* + * Flags to setdirmodes. + */ +#define FORCE 0x0001 + +/* + * Useful macros + */ +#define TSTINO(ino, map) \ + (map[(u_int)((ino) - 1) / NBBY] & (1 << ((u_int)((ino) - 1) % NBBY))) +#define SETINO(ino, map) \ + map[(u_int)((ino) - 1) / NBBY] |= 1 << ((u_int)((ino) - 1) % NBBY) + +#define Dprintf if (dflag) fprintf +#define Vprintf if (vflag) fprintf + +#define GOOD 1 +#define FAIL 0 + +#ifdef USE_QFA +#define QFA_MAGIC "495115637697" +#define QFA_VERSION "1.0" +extern FILE *gTapeposfp; +extern char *gTapeposfile; +extern char gTps[255]; +extern long gSeekstart; +extern int tapeposflag; +extern int gTapeposfd; +extern int createtapeposflag; +extern unsigned long qfadumpdate; +extern long long curtapepos; +#ifdef sunos +int fdsmtc; +long scsiid; +char smtcpath[2048]; +#endif +#endif /* USE_QFA */ + +#define do_compare_error \ + if (++compare_errors >= Lflag && Lflag) { \ + printf("Compare errors limit reached, exiting...\n"); \ + exit(2); \ + } + diff --git a/restore/symtab.c b/restore/symtab.c new file mode 100644 index 0000000..3e6d3fc --- /dev/null +++ b/restore/symtab.c @@ -0,0 +1,639 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: symtab.c,v 1.22 2003/10/26 16:05:48 stelian Exp $"; +#endif /* not lint */ + +/* + * These routines maintain the symbol table which tracks the state + * of the file system being restored. They provide lookup by either + * name or inode number. They also provide for creation, deletion, + * and renaming of entries. Because of the dynamic nature of pathnames, + * names should not be saved, but always constructed just before they + * are needed, by calling "myname". + */ + +#include +#include +#include + +#ifdef __linux__ +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#else +#include +#endif +#endif /* __linux__ */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#endif + +#include "restore.h" +#include "extern.h" + +/* + * The following variables define the inode symbol table. + * The primary hash table is dynamically allocated based on + * the number of inodes in the file system (maxino), scaled by + * HASHFACTOR. The variable "entry" points to the hash table; + * the variable "entrytblsize" indicates its size (in entries). + */ +#define HASHFACTOR 5 +static struct entry **entry; +static long entrytblsize; + +static void addino __P((dump_ino_t, struct entry *)); +static struct entry *lookupparent __P((char *)); +static void removeentry __P((struct entry *)); + +/* + * Look up an entry by inode number + */ +struct entry * +lookupino(dump_ino_t inum) +{ + struct entry *ep; + + if (inum < WINO || inum >= maxino) + return (NULL); + for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next) + if (ep->e_ino == inum) + return (ep); + return (NULL); +} + +/* + * Add an entry into the entry table + */ +static void +addino(dump_ino_t inum, struct entry *np) +{ + struct entry **epp; + + if (inum < WINO || inum >= maxino) + panic("addino: out of range %d\n", inum); + epp = &entry[inum % entrytblsize]; + np->e_ino = inum; + np->e_next = *epp; + *epp = np; + if (dflag) + for (np = np->e_next; np != NULL; np = np->e_next) + if (np->e_ino == inum) + badentry(np, "duplicate inum"); +} + +/* + * Delete an entry from the entry table + */ +void +deleteino(dump_ino_t inum) +{ + struct entry *next; + struct entry **prev; + + if (inum < WINO || inum >= maxino) + panic("deleteino: out of range %d\n", inum); + prev = &entry[inum % entrytblsize]; + for (next = *prev; next != NULL; next = next->e_next) { + if (next->e_ino == inum) { + next->e_ino = 0; + *prev = next->e_next; + return; + } + prev = &next->e_next; + } + panic("deleteino: %d not found\n", inum); +} + +/* + * Look up an entry by name + */ +struct entry * +lookupname(char *name) +{ + struct entry *ep; + char *np, *cp; + char buf[MAXPATHLEN]; + + cp = name; + for (ep = lookupino(ROOTINO); ep != NULL; ep = ep->e_entries) { + for (np = buf; *cp != '/' && *cp != '\0' && + np < &buf[sizeof(buf)]; ) + *np++ = *cp++; + if (np == &buf[sizeof(buf)]) + break; + *np = '\0'; + for ( ; ep != NULL; ep = ep->e_sibling) + if (strcmp(ep->e_name, buf) == 0) + break; + if (ep == NULL) + break; + if (*cp++ == '\0') + return (ep); + } + return (NULL); +} + +/* + * Look up the parent of a pathname + */ +static struct entry * +lookupparent(char *name) +{ + struct entry *ep; + char *tailindex; + + tailindex = strrchr(name, '/'); + if (tailindex == NULL) + return (NULL); + *tailindex = '\0'; + ep = lookupname(name); + *tailindex = '/'; + if (ep == NULL) + return (NULL); + if (ep->e_type != NODE) + panic("%s is not a directory\n", name); + return (ep); +} + +/* + * Determine the current pathname of a node or leaf + */ +char * +myname(struct entry *ep) +{ + char *cp; + static char namebuf[MAXPATHLEN]; + + for (cp = &namebuf[MAXPATHLEN - 2]; cp > &namebuf[ep->e_namlen]; ) { + cp -= ep->e_namlen; + memmove(cp, ep->e_name, (size_t)ep->e_namlen); + if (ep == lookupino(ROOTINO)) + return (cp); + *(--cp) = '/'; + ep = ep->e_parent; + } + panic("%s: pathname too long\n", cp); + return(cp); +} + +/* + * Unused symbol table entries are linked together on a free list + * headed by the following pointer. + */ +static struct entry *freelist = NULL; + +/* + * add an entry to the symbol table + */ +struct entry * +addentry(char *name, dump_ino_t inum, int type) +{ + struct entry *np, *ep; + + if (freelist != NULL) { + np = freelist; + freelist = np->e_next; + memset(np, 0, sizeof(struct entry)); + } else { + np = (struct entry *)calloc(1, sizeof(struct entry)); + if (np == NULL) + errx(1, "no memory to extend symbol table"); + } + np->e_type = type & ~LINK; + ep = lookupparent(name); + if (ep == NULL) { + if (inum != ROOTINO || lookupino(ROOTINO) != NULL) + panic("bad name to addentry %s\n", name); + np->e_name = savename(name); + np->e_namlen = strlen(name); + np->e_parent = np; + addino(ROOTINO, np); + return (np); + } + np->e_name = savename(strrchr(name, '/') + 1); + np->e_namlen = strlen(np->e_name); + np->e_parent = ep; + np->e_sibling = ep->e_entries; + ep->e_entries = np; + if (type & LINK) { + ep = lookupino(inum); + if (ep == NULL) + panic("link to non-existent name\n"); + np->e_ino = inum; + np->e_links = ep->e_links; + ep->e_links = np; + } else if (inum != 0) { + if (lookupino(inum) != NULL) + panic("duplicate entry\n"); + addino(inum, np); + } + return (np); +} + +/* + * delete an entry from the symbol table + */ +void +freeentry(struct entry *ep) +{ + struct entry *np; + dump_ino_t inum; + + if (ep->e_flags != REMOVED) + badentry(ep, "not marked REMOVED"); + if (ep->e_type == NODE) { + if (ep->e_links != NULL) + badentry(ep, "freeing referenced directory"); + if (ep->e_entries != NULL) + badentry(ep, "freeing non-empty directory"); + } + if (ep->e_ino != 0) { + np = lookupino(ep->e_ino); + if (np == NULL) + badentry(ep, "lookupino failed"); + if (np == ep) { + inum = ep->e_ino; + deleteino(inum); + if (ep->e_links != NULL) + addino(inum, ep->e_links); + } else { + for (; np != NULL; np = np->e_links) { + if (np->e_links == ep) { + np->e_links = ep->e_links; + break; + } + } + if (np == NULL) + badentry(ep, "link not found"); + } + } + removeentry(ep); + freename(ep->e_name); + ep->e_next = freelist; + freelist = ep; +} + +/* + * Relocate an entry in the tree structure + */ +void +moveentry(struct entry *ep, char *newname) +{ + struct entry *np; + char *cp; + + np = lookupparent(newname); + if (np == NULL) + badentry(ep, "cannot move ROOT"); + if (np != ep->e_parent) { + removeentry(ep); + ep->e_parent = np; + ep->e_sibling = np->e_entries; + np->e_entries = ep; + } + cp = strrchr(newname, '/') + 1; + freename(ep->e_name); + ep->e_name = savename(cp); + ep->e_namlen = strlen(cp); + if (strcmp(gentempname(ep), ep->e_name) == 0) + ep->e_flags |= TMPNAME; + else + ep->e_flags &= ~TMPNAME; +} + +/* + * Remove an entry in the tree structure + */ +static void +removeentry(struct entry *ep) +{ + struct entry *np; + + np = ep->e_parent; + if (np->e_entries == ep) { + np->e_entries = ep->e_sibling; + } else { + for (np = np->e_entries; np != NULL; np = np->e_sibling) { + if (np->e_sibling == ep) { + np->e_sibling = ep->e_sibling; + break; + } + } + if (np == NULL) + badentry(ep, "cannot find entry in parent list"); + } +} + +/* + * Table of unused string entries, sorted by length. + * + * Entries are allocated in STRTBLINCR sized pieces so that names + * of similar lengths can use the same entry. The value of STRTBLINCR + * is chosen so that every entry has at least enough space to hold + * a "struct strtbl" header. Thus every entry can be linked onto an + * appropriate free list. + * + * NB. The macro "allocsize" below assumes that "struct strhdr" + * has a size that is a power of two. + */ +struct strhdr { + struct strhdr *next; +}; + +#define STRTBLINCR (sizeof(struct strhdr)) +#define allocsize(size) (((size) + 1 + STRTBLINCR - 1) & ~(STRTBLINCR - 1)) + +static struct strhdr strtblhdr[allocsize(MAXNAMLEN) / STRTBLINCR]; + +/* + * Allocate space for a name. It first looks to see if it already + * has an appropriate sized entry, and if not allocates a new one. + */ +char * +savename(char *name) +{ + struct strhdr *np; + long len; + char *cp; + + if (name == NULL) + panic("bad name\n"); + len = strlen(name); + np = strtblhdr[len / STRTBLINCR].next; + if (np != NULL) { + strtblhdr[len / STRTBLINCR].next = np->next; + cp = (char *)np; + } else { + cp = malloc((unsigned)allocsize(len)); + if (cp == NULL) + errx(1, "no space for string table"); + } + (void) strcpy(cp, name); + return (cp); +} + +/* + * Free space for a name. The resulting entry is linked onto the + * appropriate free list. + */ +void +freename(char *name) +{ + struct strhdr *tp, *np; + + tp = &strtblhdr[strlen(name) / STRTBLINCR]; + np = (struct strhdr *)name; + np->next = tp->next; + tp->next = np; +} + +/* + * Useful quantities placed at the end of a dumped symbol table. + */ +struct symtableheader { + int32_t volno; + int32_t stringsize; + int32_t entrytblsize; + time_t dumptime; + time_t dumpdate; + dump_ino_t maxino; + int32_t ntrec; + int32_t zflag; +}; + +/* + * dump a snapshot of the symbol table + */ +void +dumpsymtable(char *filename, long checkpt) +{ + struct entry *ep, *tep; + dump_ino_t i; + struct entry temp, *tentry; + long mynum = 1, stroff = 0; + FILE *fd; + struct symtableheader hdr; + + Vprintf(stdout, "Check pointing the restore\n"); + if (Nflag) + return; + if ((fd = fopen(filename, "w")) == NULL) { + warn("fopen"); + panic("cannot create save file %s for symbol table\n", + filename); + } + clearerr(fd); + /* + * Assign indices to each entry + * Write out the string entries + */ + for (i = WINO; i <= maxino; i++) { + for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { + ep->e_index = mynum++; + (void) fwrite(ep->e_name, sizeof(char), + (int)allocsize(ep->e_namlen), fd); + } + } + /* + * Convert pointers to indexes, and output + */ + tep = &temp; + stroff = 0; + for (i = WINO; i <= maxino; i++) { + for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { + memmove(tep, ep, sizeof(struct entry)); + tep->e_name = (char *)stroff; + stroff += allocsize(ep->e_namlen); + tep->e_parent = (struct entry *)ep->e_parent->e_index; + if (ep->e_links != NULL) + tep->e_links = + (struct entry *)ep->e_links->e_index; + if (ep->e_sibling != NULL) + tep->e_sibling = + (struct entry *)ep->e_sibling->e_index; + if (ep->e_entries != NULL) + tep->e_entries = + (struct entry *)ep->e_entries->e_index; + if (ep->e_next != NULL) + tep->e_next = + (struct entry *)ep->e_next->e_index; + (void) fwrite((char *)tep, sizeof(struct entry), 1, fd); + } + } + /* + * Convert entry pointers to indexes, and output + */ + for (i = 0; (long)i < entrytblsize; i++) { + if (entry[i] == NULL) + tentry = NULL; + else + tentry = (struct entry *)entry[i]->e_index; + (void) fwrite((char *)&tentry, sizeof(struct entry *), 1, fd); + } + hdr.volno = checkpt; + hdr.maxino = maxino; + hdr.entrytblsize = entrytblsize; + hdr.stringsize = stroff; + hdr.dumptime = dumptime; + hdr.dumpdate = dumpdate; + hdr.ntrec = ntrec; + hdr.zflag = zflag; + (void) fwrite((char *)&hdr, sizeof(struct symtableheader), 1, fd); + if (ferror(fd)) { + warn("fwrite"); + panic("output error to file %s writing symbol table\n", + filename); + } + (void) fclose(fd); +} + +/* + * Initialize a symbol table from a file + */ +void +initsymtable(char *filename) +{ + char *base; + long tblsize; + struct entry *ep; + struct entry *baseep, *lep; + struct symtableheader hdr; + struct stat stbuf; + long i; + int fd; + + Vprintf(stdout, "Initialize symbol table.\n"); + if (filename == NULL) { + entrytblsize = maxino / HASHFACTOR; + entry = (struct entry **) + calloc((unsigned)entrytblsize, sizeof(struct entry *)); + if (entry == (struct entry **)NULL) + errx(1, "no memory for entry table"); + ep = addentry(".", ROOTINO, NODE); + ep->e_flags |= NEW; + return; + } + if ((fd = open(filename, O_RDONLY, 0)) < 0) { + warn("open"); + errx(1, "cannot open symbol table file %s", filename); + } + if (fstat(fd, &stbuf) < 0) { + warn("stat"); + errx(1, "cannot stat symbol table file %s", filename); + } + tblsize = stbuf.st_size - sizeof(struct symtableheader); + base = calloc(sizeof(char), (unsigned)tblsize); + if (base == NULL) + errx(1, "cannot allocate space for symbol table"); + if (read(fd, base, (int)tblsize) < 0 || + read(fd, (char *)&hdr, sizeof(struct symtableheader)) < 0) { + warn("read"); + errx(1, "cannot read symbol table file %s", filename); + } + switch (command) { + case 'r': + /* + * For normal continuation, insure that we are using + * the next incremental tape + */ + if (hdr.dumpdate != dumptime) + errx(1, "Incremental tape too %s", + (hdr.dumpdate < dumptime) ? "low" : "high"); + break; + case 'R': + /* + * For restart, insure that we are using the same tape + */ + curfile.action = SKIP; + dumptime = hdr.dumptime; + dumpdate = hdr.dumpdate; + zflag = hdr.zflag; + if (!bflag) + newtapebuf(hdr.ntrec); + getvol(hdr.volno); + break; + default: + panic("initsymtable called from command %c\n", command); + break; + } + resizemaps(maxino, hdr.maxino); + maxino = hdr.maxino; + entrytblsize = hdr.entrytblsize; + entry = (struct entry **) + (base + tblsize - (entrytblsize * sizeof(struct entry *))); + baseep = (struct entry *)(base + hdr.stringsize - sizeof(struct entry)); + lep = (struct entry *)entry; + for (i = 0; i < entrytblsize; i++) { + if (entry[i] == NULL) + continue; + entry[i] = &baseep[(long)entry[i]]; + } + for (ep = &baseep[1]; ep < lep; ep++) { + ep->e_name = base + (long)ep->e_name; + ep->e_parent = &baseep[(long)ep->e_parent]; + if (ep->e_sibling != NULL) + ep->e_sibling = &baseep[(long)ep->e_sibling]; + if (ep->e_links != NULL) + ep->e_links = &baseep[(long)ep->e_links]; + if (ep->e_entries != NULL) + ep->e_entries = &baseep[(long)ep->e_entries]; + if (ep->e_next != NULL) + ep->e_next = &baseep[(long)ep->e_next]; + } +} diff --git a/restore/tape.c b/restore/tape.c new file mode 100644 index 0000000..2f344db --- /dev/null +++ b/restore/tape.c @@ -0,0 +1,3122 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: tape.c,v 1.81 2004/05/25 10:39:31 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#else /* __linux__ */ +#ifdef sunos +#define quad_t int64_t +#include +#include +#include +#else +#include +#endif +#endif /* __linux__ */ +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif +#include + +#ifdef HAVE_ZLIB +#include +#endif /* HAVE_ZLIB */ + +#ifdef HAVE_BZLIB +#include +#endif /* HAVE_BZLIB */ + +#ifdef HAVE_LZO +#include +#endif /* HAVE_LZO */ + +#include "restore.h" +#include "extern.h" +#include "pathnames.h" + +#ifdef USE_QFA +int noresyncmesg = 0; +#endif /* USE_QFA */ +static long fssize = MAXBSIZE; +static int mt = -1; +int pipein = 0; +static int magtapein = 0; /* input is from magtape */ +static char magtape[MAXPATHLEN]; +static char magtapeprefix[MAXPATHLEN]; +static int blkcnt; +static int numtrec; +static char *tapebuf; /* input buffer for read */ +static int bufsize; /* buffer size without prefix */ +static char *tbufptr = NULL; /* active tape buffer */ +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) +static char *comprbuf; /* uncompress work buf */ +static size_t comprlen; /* size including prefix */ +#endif +static union u_spcl endoftapemark; +static long blksread; /* blocks read since last header */ +static long tpblksread = 0; /* TP_BSIZE blocks read */ +static long tapesread; +static sigjmp_buf restart; +static int gettingfile = 0; /* restart has a valid frame */ +char *host = NULL; + +static int ofile; +static char *map; +static char lnkbuf[MAXPATHLEN + 1]; +static int pathlen; + +int oldinofmt; /* old inode format conversion required */ +int Bcvt; /* Swap Bytes (for CCI or sun) */ +static int Qcvt; /* Swap quads (for sun) */ + +#define FLUSHTAPEBUF() blkcnt = ntrec + 1 + +static void accthdr __P((struct s_spcl *)); +static int checksum __P((int *)); +static void findinode __P((struct s_spcl *)); +static void findtapeblksize __P((void)); +static int gethead __P((struct s_spcl *)); +static int converthead __P((struct s_spcl *)); +static void converttapebuf __P((struct tapebuf *)); +static void readtape __P((char *)); +static void setdumpnum __P((void)); +#ifdef DUMP_MACOSX +static void xtrfilefinderinfo __P((char *, size_t)); +#endif + +static u_int swabi __P((u_int)); +#if 0 +static u_long swabl __P((u_long)); +#endif +static u_char *swab64 __P((u_char *, int)); +static u_char *swab32 __P((u_char *, int)); +static u_char *swab16 __P((u_char *, int)); +static void terminateinput __P((void)); +static void xtrfile __P((char *, size_t)); +static void xtrlnkfile __P((char *, size_t)); +static void xtrlnkskip __P((char *, size_t)); +static void xtrmap __P((char *, size_t)); +static void xtrmapskip __P((char *, size_t)); +static void xtrskip __P((char *, size_t)); +static void setmagtapein __P((void)); + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) +static void newcomprbuf __P((int)); +static void (*readtape_func) __P((char *)); +static void readtape_set __P((char *)); +static void readtape_uncompr __P((char *)); +static void readtape_comprfile __P((char *)); +static void readtape_comprtape __P((char *)); +static char *decompress_tapebuf __P((struct tapebuf *, int)); +static void msg_read_error __P((char *)); +#endif +static int read_a_block __P((int, char *, size_t, long *)); +#define PREFIXSIZE sizeof(struct tapebuf) + +#define COMPARE_ONTHEFLY 1 + +#if COMPARE_ONTHEFLY +static int ifile; /* input file for compare */ +static int cmperror; /* compare error */ +static void xtrcmpfile __P((char *, size_t)); +static void xtrcmpskip __P((char *, size_t)); +#endif + +static int readmapflag; +static int readingmaps; /* set to 1 while reading the maps */ + +#ifdef DUMP_MACOSX +static DumpFinderInfo gFndrInfo; +#endif + +/* + * Set up an input source. This is called from main.c before setup() is. + */ +void +setinput(char *source) +{ + int i; + char *n; + + FLUSHTAPEBUF(); + if (bflag) + newtapebuf(ntrec); + else + newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); + terminal = stdin; + +#ifdef RRESTORE + if ((n = strchr(source, ':'))) { + for (i = 0; i < (n - source); i++) { + if (source[i] == '/') + break; + } + if (source[i] != '/') { + host = source; + source = strchr(host, ':'); + *source++ = '\0'; + if (rmthost(host) == 0) + exit(1); + } + } else +#endif + if (strcmp(source, "-") == 0) { + /* + * Since input is coming from a pipe we must establish + * our own connection to the terminal. + */ + terminal = fopen(_PATH_TTY, "r"); + if (terminal == NULL) { + warn("cannot open %s", _PATH_TTY); + terminal = fopen(_PATH_DEVNULL, "r"); + if (terminal == NULL) + err(1, "cannot open %s", _PATH_DEVNULL); + } + pipein++; + } + setuid(getuid()); /* no longer need or want root privileges */ + if (Mflag) { + strncpy(magtapeprefix, source, MAXPATHLEN); + magtapeprefix[MAXPATHLEN-1] = '\0'; + snprintf(magtape, MAXPATHLEN, "%s%03d", source, 1); + } + else + strncpy(magtape, source, MAXPATHLEN); + magtape[MAXPATHLEN - 1] = '\0'; +} + +void +newtapebuf(long size) +{ + static int tapebufsize = -1; + + ntrec = size; + bufsize = ntrec * TP_BSIZE; + if (size <= tapebufsize) + return; + if (tapebuf != NULL) + free(tapebuf); + tapebuf = malloc(size * TP_BSIZE + sizeof(struct tapebuf)); + if (tapebuf == NULL) + errx(1, "Cannot allocate space for tape buffer"); + tapebufsize = size; +} + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) +static void +newcomprbuf(int size) +{ + size_t buf_size = (size+1) * TP_BSIZE + sizeof(struct tapebuf); + if (buf_size <= comprlen) + return; + comprlen = buf_size; + if (comprbuf != NULL) + free(comprbuf); + comprbuf = malloc(comprlen); + if (comprbuf == NULL) + errx(1, "Cannot allocate space for decompress buffer"); +} +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + +/* + * Verify that the tape drive can be accessed and + * that it actually is a dump tape. + */ +void +setup(void) +{ + int i, j, *ip, bot_code; + struct STAT stbuf; + char *temptape; + + Vprintf(stdout, "Verify tape and initialize maps\n"); + if (Afile == NULL && bot_script) { + msg("Launching %s\n", bot_script); + bot_code = system_command(bot_script, magtape, 1); + if (bot_code != 0 && bot_code != 1) { + msg("Restore aborted by the beginning of tape script\n"); + exit(1); + } + } + + if (Afile) + temptape = Afile; + else + temptape = magtape; + +#ifdef RRESTORE + if (!Afile && host) + mt = rmtopen(temptape, O_RDONLY); + else +#endif + if (pipein) + mt = 0; + else + mt = OPEN(temptape, O_RDONLY, 0); + if (mt < 0) + err(1, "%s", temptape); + if (!Afile) { + volno = 1; + setmagtapein(); + setdumpnum(); + } +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + readtape_func = readtape_set; +#if defined(HAVE_LZO) + if (lzo_init() != LZO_E_OK) { + msg("internal error - lzo_init failed \n"); + exit(1); + } +#endif +#endif + FLUSHTAPEBUF(); + findtapeblksize(); + if (gethead(&spcl) == FAIL) { + blkcnt--; /* push back this block */ + blksread--; + tpblksread--; + cvtflag++; + if (gethead(&spcl) == FAIL) + errx(1, "Tape is not a dump tape"); + fprintf(stderr, "Converting to new file system format.\n"); + } + + if (zflag) { + fprintf(stderr, "Dump tape is compressed.\n"); +#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB) && !defined(HAVE_LZO) + errx(1,"This restore version doesn't support decompression"); +#endif /* !HAVE_ZLIB && !HAVE_BZLIB */ + } + if (pipein) { + endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; + endoftapemark.s_spcl.c_type = TS_END; + ip = (int *)&endoftapemark; + j = sizeof(union u_spcl) / sizeof(int); + i = 0; + do + i += *ip++; + while (--j); + endoftapemark.s_spcl.c_checksum = CHECKSUM - i; + } + if (vflag || command == 't' || command == 'C') + printdumpinfo(); +#ifdef USE_QFA + if (tapeposflag && (unsigned long)spcl.c_date != qfadumpdate) + errx(1, "different QFA/dumpdates detected\n"); +#endif + if (filesys[0] == '\0') { + char *dirptr; + strncpy(filesys, spcl.c_filesys, NAMELEN); + filesys[NAMELEN - 1] = '\0'; + dirptr = strstr(filesys, " (dir"); + if (dirptr != NULL) + *dirptr = '\0'; + } + dumptime = spcl.c_ddate; + dumpdate = spcl.c_date; + if (STAT(".", &stbuf) < 0) + err(1, "cannot stat ."); + if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE ) + fssize = TP_BSIZE; + if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) + fssize = stbuf.st_blksize; + if (((fssize - 1) & fssize) != 0) + errx(1, "bad block size %ld", fssize); + if (spcl.c_volume != 1) + errx(1, "Tape is not volume 1 of the dump"); + if (gethead(&spcl) == FAIL) { + Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread); + panic("no header after volume mark!\n"); + } + readingmaps = 1; + findinode(&spcl); + if (spcl.c_type != TS_CLRI) + errx(1, "Cannot find file removal list"); + maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; + map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); + if (map == NULL) + errx(1, "no memory for active inode map"); + usedinomap = map; + curfile.action = USING; + getfile(xtrmap, xtrmapskip); + while (spcl.c_type == TS_ADDR) { + /* Recompute maxino and the map */ + dump_ino_t oldmaxino = maxino; + maxino += (spcl.c_count * TP_BSIZE * NBBY) + 1; + resizemaps(oldmaxino, maxino); + map = usedinomap; + + spcl.c_dinode.di_size = spcl.c_count * TP_BSIZE; + getfile(xtrmap, xtrmapskip); + } + Dprintf(stdout, "maxino = %lu\n", (unsigned long)maxino); + if (spcl.c_type != TS_BITS) { + if (spcl.c_type == TS_END) { + msg("Cannot find file dump list, assuming empty tape\n"); + exit(0); + } + errx(1, "Cannot find file dump list"); + } + map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); + if (map == (char *)NULL) + errx(1, "no memory for file dump list"); + dumpmap = map; + curfile.action = USING; + getfile(xtrmap, xtrmapskip); + while (spcl.c_type == TS_ADDR) { + spcl.c_dinode.di_size = spcl.c_count * TP_BSIZE; + getfile(xtrmap, xtrmapskip); + } + /* + * If there may be whiteout entries on the tape, pretend that the + * whiteout inode exists, so that the whiteout entries can be + * extracted. + */ + if (oldinofmt == 0) + SETINO(WINO, dumpmap); + readingmaps = 0; + findinode(&spcl); +} + +/* + * Prompt user to load a new dump volume. + * "Nextvol" is the next suggested volume to use. + * This suggested volume is enforced when doing full + * or incremental restores, but can be overridden by + * the user when only extracting a subset of the files. + */ +void +getvol(long nextvol) +{ + long newvol = 0, wantnext = 0, i; + long saved_blksread = 0, saved_tpblksread = 0; + union u_spcl tmpspcl; +# define tmpbuf tmpspcl.s_spcl + char buf[TP_BSIZE]; + int haderror = 0, bot_code = 1; + + if (nextvol == 1) { + tapesread = 0; + gettingfile = 0; + tpblksread = 0; + blksread = 0; + } + if (pipein) { + if (nextvol != 1) + panic("Changing volumes on pipe input?\n"); + if (volno == 1) + return; + goto gethdr; + } + saved_blksread = blksread; + saved_tpblksread = tpblksread; +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) + close(fdsmtc); +#endif +again: + if (pipein) + exit(1); /* pipes do not get a second chance */ + if (aflag || curfile.action != SKIP) { + newvol = nextvol; + wantnext = 1; + } else { + newvol = 0; + wantnext = 0; + } + while (newvol <= 0) { + if (tapesread == 0) { + fprintf(stderr, "%s%s%s%s%s", + "You have not read any volumes yet.\n", + "Unless you know which volume your", + " file(s) are on you should start\n", + "with the last volume and work", + " towards the first.\n"); + } else { + fprintf(stderr, "You have read volumes"); + strcpy(buf, ": "); + for (i = 1; i < 32; i++) + if (tapesread & (1 << i)) { + fprintf(stderr, "%s%ld", buf, (long)i); + strcpy(buf, ", "); + } + fprintf(stderr, "\n"); + } + do { + fprintf(stderr, "Specify next volume # (none if no more volumes): "); + (void) fflush(stderr); + (void) fgets(buf, TP_BSIZE, terminal); + } while (!feof(terminal) && buf[0] == '\n'); + if (feof(terminal)) + exit(1); + if (!strcmp(buf, "none\n")) { + terminateinput(); + return; + } + newvol = atoi(buf); + if (newvol <= 0) { + fprintf(stderr, + "Volume numbers are positive numerics\n"); + } + } + if (newvol == volno) { + tapesread |= 1 << volno; +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) { + if (OpenSMTCmt(magtape) < 0) { + volno = -1; + haderror = 1; + goto again; + } + } +#endif /* USE_QFA */ + return; + } + closemt(); + + /* + * if using an archive file, reset its name so readtape() + * could properly use remote access. + */ + Afile = NULL; + + if (Mflag) { + snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol); + magtape[MAXPATHLEN - 1] = '\0'; + } + if (bot_script && !haderror) { + msg("Launching %s\n", bot_script); + bot_code = system_command(bot_script, magtape, newvol); + if (bot_code != 0 && bot_code != 1) { + msg("Restore aborted by the beginning of tape script\n"); + exit(1); + } + } + if (haderror || (bot_code && !Mflag)) { + haderror = 0; +#ifdef sunos + fprintf(stderr, "Mount volume %ld\n", (long)newvol); +#else + fprintf(stderr, "Mount tape volume %ld\n", (long)newvol); +#endif + fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); +#ifdef sunos + fprintf(stderr, "then enter volume name (default: %s) ", magtape); +#else + fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); +#endif + (void) fflush(stderr); + (void) fgets(buf, TP_BSIZE, terminal); + if (feof(terminal)) + exit(1); + if (!strcmp(buf, "none\n")) { + terminateinput(); + return; + } + if (buf[0] != '\n') { + char *pos; + (void) strncpy(magtape, buf, sizeof(magtape)); + magtape[sizeof(magtape) - 1] = '\0'; + if ((pos = strchr(magtape, '\n'))) + magtape[pos - magtape] = '\0'; + } + } +#if defined(USE_QFA) && defined(sunos) + if (createtapeposflag || tapeposflag) { + if (OpenSMTCmt(magtape) < 0) { + volno = -1; + haderror = 1; + goto again; + } + } +#endif /* USE_QFA */ +#ifdef RRESTORE + if (host) + mt = rmtopen(magtape, O_RDONLY); + else +#endif + mt = OPEN(magtape, O_RDONLY, 0); + + if (mt == -1) { + fprintf(stderr, "Cannot open %s\n", magtape); + volno = -1; + haderror = 1; + goto again; + } +gethdr: + setmagtapein(); +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + readtape_func = readtape_set; +#endif + volno = newvol; + setdumpnum(); + FLUSHTAPEBUF(); + findtapeblksize(); + if (gethead(&tmpbuf) == FAIL) { + Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread); + fprintf(stderr, "tape is not dump tape\n"); + volno = 0; + haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; + goto again; + } + if (tmpbuf.c_volume != volno) { + fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume); + volno = 0; + haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; + goto again; + } + if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { + fprintf(stderr, "Wrong dump date\n\tgot: %s", +#ifdef sunos + ctime(&tmpbuf.c_date)); +#else + ctime4(&tmpbuf.c_date)); +#endif + fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); + volno = 0; + haderror = 1; + blksread = saved_blksread; + tpblksread = saved_tpblksread; + goto again; + } + tapesread |= 1 << volno; + /* + * If continuing from the previous volume, skip over any + * blocks read already at the end of the previous volume. + * + * If coming to this volume at random, skip to the beginning + * of the next record. + */ + if (zflag) { + fprintf(stderr, "Dump tape is compressed.\n"); +#if !defined(HAVE_ZLIB) && !defined(HAVE_BZLIB) && !defined(HAVE_LZO) + errx(1,"This restore version doesn't support decompression"); +#endif /* !HAVE_ZLIB && !HAVE_BZLIB */ + } + Dprintf(stdout, "read %ld recs, tape starts with %ld\n", + tpblksread - 1, (long)tmpbuf.c_firstrec); + if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { + if (!wantnext) { + tpblksread = tmpbuf.c_firstrec + 1; + for (i = tmpbuf.c_count; i > 0; i--) + readtape(buf); + } else if (tmpbuf.c_firstrec > 0 && + tmpbuf.c_firstrec < tpblksread - 1) { + /* + * -1 since we've read the volume header + */ + i = tpblksread - tmpbuf.c_firstrec - 1; + Dprintf(stderr, "Skipping %ld duplicate record%s.\n", + (long)i, i > 1 ? "s" : ""); + while (--i >= 0) + readtape(buf); + } + } + if (curfile.action == USING) { + if (volno == 1) + panic("active file into volume 1\n"); + return; + } + /* + * Skip up to the beginning of the next record + */ + if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) + for (i = tmpbuf.c_count; i > 0; i--) + readtape(buf); + (void) gethead(&spcl); + findinode(&spcl); + if (gettingfile) { + gettingfile = 0; + siglongjmp(restart, 1); + } +} + +/* + * Handle unexpected EOF. + */ +static void +terminateinput(void) +{ + + if (gettingfile && curfile.action == USING) { + printf("Warning: %s %s\n", + "End-of-input encountered while extracting", curfile.name); + } + curfile.name = ""; + curfile.action = UNKNOWN; + curfile.dip = NULL; + curfile.ino = maxino; + if (gettingfile) { + gettingfile = 0; + siglongjmp(restart, 1); + } +} + +/* + * handle multiple dumps per tape by skipping forward to the + * appropriate one. + */ +static void +setdumpnum(void) +{ + struct mtop tcom; + + if (dumpnum == 1 || volno != 1) + return; + if (pipein) + errx(1, "Cannot have multiple dumps on pipe input"); + tcom.mt_op = MTFSF; + tcom.mt_count = dumpnum - 1; +#ifdef RRESTORE + if (host) { + if (rmtioctl(MTFSF, dumpnum - 1) < 0) { + fprintf(stderr, "rmtioctl MTFSF: %s\n", strerror(errno)); + exit(1); + } + } else +#endif + if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) { + fprintf(stderr, "rmtioctl MTFSF: %s\n", strerror(errno)); + exit(1); + /* warn("ioctl MTFSF"); */ + } +} + +void +printdumpinfo(void) +{ +#ifdef sunos + Vprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); + Vprintf(stdout, "Dumped from: %s", + (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate)); + if (spcl.c_host[0] == '\0') + return; + Vprintf(stdout, "Level %d dump of %s on %s:%s\n", + spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); + Vprintf(stdout, "Label: %s\n", spcl.c_label); +#else + fprintf(stdout, "Dump date: %s", ctime4(&spcl.c_date)); + fprintf(stdout, "Dumped from: %s", + (spcl.c_ddate == 0) ? "the epoch\n" : ctime4(&spcl.c_ddate)); + if (spcl.c_host[0] == '\0') + return; + fprintf(stdout, "Level %d dump of %s on %s:%s\n", + spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); + fprintf(stdout, "Label: %s\n", spcl.c_label); +#endif +} + +void +printvolinfo(void) +{ + int i; + + if (volinfo[1] == ROOTINO) { + printf("Starting inode numbers by volume:\n"); + for (i = 1; i < (int)TP_NINOS && volinfo[i] != 0; ++i) + printf("\tVolume %d: %lu\n", i, (unsigned long)volinfo[i]); + } +} + + +int +extractfile(struct entry *ep, int doremove) +{ + unsigned int flags; + mode_t mode; + struct timeval timep[2]; + char *name = myname(ep); + + /* If removal is requested (-r mode) do remove it unless + * we are extracting a metadata only inode */ + if (spcl.c_flags & DR_METAONLY) { + Vprintf(stdout, "file %s is metadata only\n", name); + } + else { + if (doremove) { + removeleaf(ep); + ep->e_flags &= ~REMOVED; + } + } + + curfile.name = name; + curfile.action = USING; +#if defined(__linux__) || defined(sunos) + timep[0].tv_sec = curfile.dip->di_atime.tv_sec; + timep[0].tv_usec = curfile.dip->di_atime.tv_usec; + timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; + timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; +#else /* __linux__ || sunos */ + timep[0].tv_sec = curfile.dip->di_atime; + timep[0].tv_usec = curfile.dip->di_atimensec / 1000; + timep[1].tv_sec = curfile.dip->di_mtime; + timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; +#endif /* __linux__ */ + mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + switch (mode & IFMT) { + + default: + fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFSOCK: + Vprintf(stdout, "skipped socket %s\n", name); + skipfile(); + return (GOOD); + + case IFDIR: + if (mflag) { + if (ep == NULL || ep->e_flags & EXTRACT) + panic("unextracted directory %s\n", name); + skipfile(); + return (GOOD); + } + Vprintf(stdout, "extract file %s\n", name); + return (genliteraldir(name, curfile.ino)); + + case IFLNK: + { +#ifdef HAVE_LCHOWN + uid_t luid = curfile.dip->di_uid; + gid_t lgid = curfile.dip->di_gid; +#endif + if (! (spcl.c_flags & DR_METAONLY)) { + lnkbuf[0] = '\0'; + pathlen = 0; + getfile(xtrlnkfile, xtrlnkskip); + if (pathlen == 0) { + Vprintf(stdout, + "%s: zero length symbolic link (ignored)\n", name); + return (GOOD); + } + if (linkit(lnkbuf, name, SYMLINK) == FAIL) + return (FAIL); + } + else + skipfile(); + +#ifdef HAVE_LCHOWN + (void) lchown(name, luid, lgid); +#endif + return (GOOD); + } + + case IFIFO: + Vprintf(stdout, "extract fifo %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag && !Nflag) + (void)unlink(name); + if (mkfifo(name, mode) < 0) { + warn("%s: cannot create fifo", name); + skipfile(); + return (FAIL); + } + } + (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); + (void) chmod(name, mode); + if (flags) +#ifdef __linux__ + (void) fsetflags(name, flags); +#else +#ifdef sunos + { + warn("%s: cannot call chflags", name); + /* (void) chflags(name, flags); */ + } +#else + (void) chflags(name, flags); +#endif +#endif + skipfile(); + utimes(name, timep); + return (GOOD); + + case IFCHR: + case IFBLK: + Vprintf(stdout, "extract special file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag) + (void)unlink(name); + if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { + warn("%s: cannot create special file", name); + skipfile(); + return (FAIL); + } + } + (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); + (void) chmod(name, mode); + if (flags) +#ifdef __linux__ + { + warn("%s: fsetflags called on a special file", name); + (void) fsetflags(name, flags); + } +#else +#ifdef sunos + { + warn("%s: cannot call chflags on a special file", name); + /* (void) chflags(name, flags); */ + } +#else + { + warn("%s: chflags called on a special file", name); + (void) chflags(name, flags); + } +#endif +#endif + skipfile(); + utimes(name, timep); + return (GOOD); + + case IFREG: + { + uid_t luid = curfile.dip->di_uid; + gid_t lgid = curfile.dip->di_gid; + + Vprintf(stdout, "extract file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + if (! (spcl.c_flags & DR_METAONLY)) { + if (uflag) + (void)unlink(name); + if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC, + 0666)) < 0) { + warn("%s: cannot create file", name); + skipfile(); + return (FAIL); + } + getfile(xtrfile, xtrskip); + (void) close(ofile); + } + else + skipfile(); + (void) chown(name, luid, lgid); + (void) chmod(name, mode); + if (flags) +#ifdef __linux__ + (void) fsetflags(name, flags); +#else +#ifdef sunos + { + warn("%s: cannot call chflags", name); + /* (void) chflags(name, flags); */ + } +#else + (void) chflags(name, flags); +#endif +#endif + utimes(name, timep); + return (GOOD); + } + } + /* NOTREACHED */ +} + +#ifdef DUMP_MACOSX +int +extractfinderinfoufs(char *name) +{ + int err; + char oFileRsrc[MAXPATHLEN]; + int flags; + mode_t mode; + struct timeval timep[2]; + u_int32_t uid; + u_int32_t gid; + char path[MAXPATHLEN], fname[MAXPATHLEN]; + int toto; + + curfile.name = name; + curfile.action = USING; + timep[0].tv_sec = curfile.dip->di_atime.tv_sec; + timep[0].tv_usec = curfile.dip->di_atime.tv_usec; + timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; + timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; + mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + uid = curfile.dip->di_uid; + gid = curfile.dip->di_gid; + + switch (mode & IFMT) { + + default: + fprintf(stderr, "%s: (extr. finfoufs) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFDIR: + fprintf(stderr, "%s: (extr. finfoufs[IFDIR]) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFLNK: + skipfile(); + return (GOOD); + + case IFREG: + Vprintf(stdout, "extract finderinfo file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + getfile(xtrfilefinderinfo, xtrskip); + + GetPathFile(name, path, fname); + strcpy(oFileRsrc, path); + strcat(oFileRsrc, "._"); + strcat(oFileRsrc, fname); + + if ((err = CreateAppleDoubleFileRes(oFileRsrc, &gFndrInfo.fndrinfo, + mode, flags, timep, uid, gid)) != 0) { + fprintf(stderr, "%s: cannot create finderinfo: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + return (GOOD); + } + /* NOTREACHED */ +} + + +int +extractresourceufs(char *name) +{ + char oFileRsrc[MAXPATHLEN]; + int flags; + mode_t mode; + struct timeval timep[2]; + char path[MAXPATHLEN], fname[MAXPATHLEN]; + ASDHeaderPtr hp; + ASDEntryPtr ep; + u_long loff; + u_int32_t uid; + u_int32_t gid; + u_int64_t di_size; + char *p; + char buf[1024]; + + curfile.name = name; + curfile.action = USING; + timep[0].tv_sec = curfile.dip->di_atime.tv_sec; + timep[0].tv_usec = curfile.dip->di_atime.tv_usec; + timep[1].tv_sec = curfile.dip->di_mtime.tv_sec; + timep[1].tv_usec = curfile.dip->di_mtime.tv_usec; + mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; + uid = curfile.dip->di_uid; + gid = curfile.dip->di_gid; + di_size = curfile.dip->di_size; + + switch (mode & IFMT) { + + default: + fprintf(stderr, "%s: (extr. resufs) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFDIR: + fprintf(stderr, "%s: (extr. resufs [IFDIR]) unknown file mode 0%o\n", name, mode); + skipfile(); + return (FAIL); + + case IFLNK: + skipfile(); + return (GOOD); + + case IFREG: + Vprintf(stdout, "extract resource file %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + + GetPathFile(name, path, fname); + strcpy(oFileRsrc, path); + strcat(oFileRsrc, "._"); + strcat(oFileRsrc, fname); + + if ((ofile = open(oFileRsrc, O_RDONLY, 0)) < 0) { + fprintf(stderr, "%s: cannot read finderinfo: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + read(ofile, buf, 70); + (void) close(ofile); + p = buf; + hp = (ASDHeaderPtr)p; + /* the header */ + hp->entries++; + p += sizeof(ASDHeader) - CORRECT; + ep = (ASDEntryPtr)p; + /* the finderinfo entry */ + ep->offset += sizeof(ASDEntry); + loff = ep->offset; + + p += sizeof(ASDEntry); + /* the finderinfo data */ + bcopy(p, p + sizeof(ASDEntry), INFOLEN); + ep = (ASDEntryPtr)p; + /* the new resourcefork entry */ + ep->entryID = EntryRSRCFork; + ep->offset = loff + INFOLEN; + ep->len = di_size; + /* write the new appledouble entries to the file */ + if ((ofile = open(oFileRsrc, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + fprintf(stderr, "%s: cannot create resource file: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + write(ofile, buf, 70 + sizeof(ASDEntry)); + /* and add the resource data from tape */ + getfile(xtrfile, xtrskip); + + (void) fchown(ofile, uid, gid); + (void) fchmod(ofile, mode); + (void) close(ofile); + (void) fsetflags(oFileRsrc, flags); + utimes(oFileRsrc, timep); + return (GOOD); + } + /* NOTREACHED */ +} +#endif /* DUMP_MACOSX */ + +/* + * skip over bit maps on the tape + */ +void +skipmaps(void) +{ + + while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) + skipfile(); +} + +/* + * skip over a file on the tape + */ +void +skipfile(void) +{ + + curfile.action = SKIP; + getfile(xtrnull, xtrnull); +} + +/* + * Extract a file from the tape. + * When an allocated block is found it is passed to the fill function; + * when an unallocated block (hole) is found, a zeroed buffer is passed + * to the skip function. + */ +void +getfile(void (*fill) __P((char *, size_t)), void (*skip) __P((char *, size_t))) +{ + int i; + volatile int curblk = 0; + volatile quad_t size = spcl.c_dinode.di_size; + volatile int last_write_was_hole = 0; + quad_t origsize = size; + static char clearedbuf[MAXBSIZE]; + char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; + char junk[TP_BSIZE]; + + if (spcl.c_type == TS_END) + panic("ran off end of tape\n"); + if (spcl.c_magic != NFS_MAGIC) + panic("not at beginning of a file\n"); + if (!gettingfile && setjmp(restart) != 0) + return; + gettingfile++; +loop: + for (i = 0; i < spcl.c_count; i++) { + if (readmapflag || spcl.c_addr[i]) { + readtape(&buf[curblk++][0]); + if (curblk == fssize / TP_BSIZE) { + (*fill)((char *)buf, (size_t)(size > TP_BSIZE ? + fssize : (curblk - 1) * TP_BSIZE + size)); + curblk = 0; + last_write_was_hole = 0; + } + } else { + if (curblk > 0) { + (*fill)((char *)buf, (size_t)(size > TP_BSIZE ? + curblk * TP_BSIZE : + (curblk - 1) * TP_BSIZE + size)); + curblk = 0; + } + (*skip)(clearedbuf, (long)(size > TP_BSIZE ? + TP_BSIZE : size)); + last_write_was_hole = 1; + } + if ((size -= TP_BSIZE) <= 0) { + for (i++; i < spcl.c_count; i++) + if (readmapflag || spcl.c_addr[i]) + readtape(junk); + break; + } + } + if (gethead(&spcl) == GOOD && size > 0) { + if (spcl.c_type == TS_ADDR) + goto loop; + Dprintf(stdout, + "Missing address (header) block for %s at %ld blocks\n", + curfile.name, (long)blksread); + } + if (curblk > 0) { + (*fill)((char *)buf, (size_t)((curblk * TP_BSIZE) + size)); + last_write_was_hole = 0; + } + if (size > 0) { + fprintf(stderr, "Missing blocks at the end of %s, assuming hole\n", curfile.name); + while (size > 0) { + size_t skp = size > TP_BSIZE ? TP_BSIZE : size; + (*skip)(clearedbuf, skp); + size -= skp; + } + last_write_was_hole = 1; + } + if (last_write_was_hole) { + FTRUNCATE(ofile, origsize); + } + if (!readingmaps) + findinode(&spcl); + gettingfile = 0; +} + +/* + * Write out the next block of a file. + */ +static void +xtrfile(char *buf, size_t size) +{ + + if (Nflag) + return; + if (write(ofile, buf, (int) size) == -1) + err(1, "write error extracting inode %lu, name %s\nwrite", + (unsigned long)curfile.ino, curfile.name); +} + +#ifdef DUMP_MACOSX +static void +xtrfilefinderinfo(char *buf, size_t size) +{ + if (Nflag) + return; + bcopy(buf, &gFndrInfo, size); +} +#endif /* DUMP_MACOSX */ + +/* + * Skip over a hole in a file. + */ +/* ARGSUSED */ +static void +xtrskip(UNUSED(char *buf), size_t size) +{ + + if (LSEEK(ofile, (OFF_T)size, SEEK_CUR) == -1) + err(1, "seek error extracting inode %lu, name %s\nlseek", + (unsigned long)curfile.ino, curfile.name); +} + +/* + * Collect the next block of a symbolic link. + */ +static void +xtrlnkfile(char *buf, size_t size) +{ + + pathlen += size; + if (pathlen > MAXPATHLEN) + errx(1, "symbolic link name: %s->%s%s; too long %d", + curfile.name, lnkbuf, buf, pathlen); + (void) strcat(lnkbuf, buf); +} + +/* + * Skip over a hole in a symbolic link (should never happen). + */ +/* ARGSUSED */ +static void +xtrlnkskip(UNUSED(char *buf), UNUSED(size_t size)) +{ + + errx(1, "unallocated block in symbolic link %s", curfile.name); +} + +/* + * Collect the next block of a bit map. + */ +static void +xtrmap(char *buf, size_t size) +{ + + memmove(map, buf, size); + map += size; +} + +/* + * Skip over a hole in a bit map (should never happen). + */ +/* ARGSUSED */ +static void +xtrmapskip(UNUSED(char *buf), size_t size) +{ + + panic("hole in map\n"); + map += size; +} + +/* + * Noop, when an extraction function is not needed. + */ +/* ARGSUSED */ +void +xtrnull(UNUSED(char *buf), UNUSED(size_t size)) +{ + + return; +} + +#if COMPARE_ONTHEFLY +/* + * Compare the next block of a file. + */ +static void +xtrcmpfile(char *buf, size_t size) +{ + static char cmpbuf[MAXBSIZE]; + + if (cmperror) + return; + + if (read(ifile, cmpbuf, size) != (ssize_t)size) { + fprintf(stderr, "%s: size has changed.\n", + curfile.name); + cmperror = 1; + return; + } + + if (memcmp(buf, cmpbuf, size) != 0) { + fprintf(stderr, "%s: tape and disk copies are different\n", + curfile.name); + cmperror = 1; + return; + } +} + +/* + * Skip over a hole in a file. + */ +static void +xtrcmpskip(UNUSED(char *buf), size_t size) +{ + static char cmpbuf[MAXBSIZE]; + int i; + + if (cmperror) + return; + + if (read(ifile, cmpbuf, size) != (ssize_t)size) { + fprintf(stderr, "%s: size has changed.\n", + curfile.name); + cmperror = 1; + return; + } + + for (i = 0; i < (int)size; ++i) + if (cmpbuf[i] != '\0') { + fprintf(stderr, "%s: tape and disk copies are different\n", + curfile.name); + cmperror = 1; + return; + } +} +#endif /* COMPARE_ONTHEFLY */ + +#if !COMPARE_ONTHEFLY +static int +do_cmpfiles(int fd_tape, int fd_disk, long size) +{ + static char buf_tape[BUFSIZ]; + static char buf_disk[BUFSIZ]; + ssize_t n_tape; + ssize_t n_disk; + + while (size > 0) { + if ((n_tape = read(fd_tape, buf_tape, sizeof(buf_tape))) < 1) { + close(fd_tape), close(fd_disk); + panic("do_cmpfiles: unexpected EOF[1]"); + } + if ((n_disk = read(fd_disk, buf_disk, sizeof(buf_tape))) < 1) { + close(fd_tape), close(fd_disk); + panic("do_cmpfiles: unexpected EOF[2]"); + } + if (n_tape != n_disk) { + close(fd_tape), close(fd_disk); + panic("do_cmpfiles: sizes different!"); + } + if (memcmp(buf_tape, buf_disk, (size_t)n_tape) != 0) return (1); + size -= n_tape; + } + return (0); +} + +/* for debugging compare problems */ +#undef COMPARE_FAIL_KEEP_FILE + +static +#ifdef COMPARE_FAIL_KEEP_FILE +/* return true if tapefile should be unlinked after compare */ +int +#else +void +#endif +cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk) +{ + struct STAT sbuf_tape; + int fd_tape, fd_disk; + + if (STAT(tapefile, &sbuf_tape) != 0) { + panic("Can't lstat tmp file %s: %s\n", tapefile, + strerror(errno)); + do_compare_error; + } + + if (sbuf_disk->st_size != sbuf_tape.st_size) { + fprintf(stderr, + "%s: size changed from %ld to %ld.\n", + diskfile, (long)sbuf_tape.st_size, (long)sbuf_disk->st_size); + do_compare_error; +#ifdef COMPARE_FAIL_KEEP_FILE + return (0); +#else + return; +#endif + } + + if ((fd_tape = OPEN(tapefile, O_RDONLY)) < 0) { + panic("Can't open %s: %s\n", tapefile, strerror(errno)); + do_compare_error; + } + if ((fd_disk = OPEN(diskfile, O_RDONLY)) < 0) { + close(fd_tape); + panic("Can't open %s: %s\n", diskfile, strerror(errno)); + do_compare_error; + } + + if (do_cmpfiles(fd_tape, fd_disk, sbuf_tape.st_size)) { + fprintf(stderr, "%s: tape and disk copies are different\n", + diskfile); + close(fd_tape); + close(fd_disk); + do_compare_error; +#ifdef COMPARE_FAIL_KEEP_FILE + /* rename the file to live in /tmp */ + /* rename `tapefile' to /tmp/ */ + { + char *p = strrchr(diskfile, '/'); + char newname[MAXPATHLEN]; + if (!p) { + panic("can't find / in %s\n", diskfile); + } + snprintf(newname, sizeof(newname), "%s/debug/%s", tmpdir, p + 1); + if (rename(tapefile, newname)) { + panic("rename from %s to %s failed: %s\n", + tapefile, newname, + strerror(errno)); + } else { + fprintf(stderr, "*** %s saved to %s\n", + tapefile, newname); + } + } + + /* don't unlink the file (it's not there anymore */ + /* anyway) */ + return (0); +#else + return; +#endif + } + close(fd_tape); + close(fd_disk); +#ifdef COMPARE_FAIL_KEEP_FILE + return (1); +#endif +} +#endif /* !COMPARE_ONTHEFLY */ + +#if !COMPARE_ONTHEFLY +static char tmpfilename[MAXPATHLEN]; +#endif + +void +comparefile(char *name) +{ + unsigned int mode; + struct STAT sb; + int r; +#if !COMPARE_ONTHEFLY + static char *tmpfile = NULL; + struct STAT stemp; +#endif + + curfile.name = name; + curfile.action = USING; + mode = curfile.dip->di_mode; + + if ((mode & IFMT) == IFSOCK) { + Vprintf(stdout, "skipped socket %s\n", name); + skipfile(); + return; + } + + if ((r = LSTAT(name, &sb)) != 0) { + warn("%s: does not exist (%d)", name, r); + do_compare_error; + skipfile(); + return; + } + + Vprintf(stdout, "comparing %s (size: %ld, mode: 0%o)\n", name, + (long)sb.st_size, mode); + + if (sb.st_mode != mode) { + fprintf(stderr, "%s: mode changed from 0%o to 0%o.\n", + name, mode & 07777, sb.st_mode & 07777); + do_compare_error; + } + if (spcl.c_flags & DR_METAONLY) { + skipfile(); + return; + } + switch (mode & IFMT) { + default: + skipfile(); + return; + + case IFSOCK: + skipfile(); + return; + + case IFDIR: + skipfile(); + return; + + case IFLNK: { + char lbuf[MAXPATHLEN + 1]; + int lsize; + + if (!(sb.st_mode & S_IFLNK)) { + fprintf(stderr, "%s: is no longer a symbolic link\n", + name); + do_compare_error; + return; + } + lnkbuf[0] = '\0'; + pathlen = 0; + getfile(xtrlnkfile, xtrlnkskip); + if (pathlen == 0) { + fprintf(stderr, + "%s: zero length symbolic link (ignored)\n", + name); + do_compare_error; + return; + } + if ((lsize = readlink(name, lbuf, MAXPATHLEN)) < 0) { + panic("readlink of %s failed: %s", name, + strerror(errno)); + do_compare_error; + } + lbuf[lsize] = 0; + if (strcmp(lbuf, lnkbuf) != 0) { + fprintf(stderr, + "%s: symbolic link changed from %s to %s.\n", + name, lnkbuf, lbuf); + do_compare_error; + return; + } + return; + } + + case IFCHR: + case IFBLK: + if (!(sb.st_mode & (S_IFCHR|S_IFBLK))) { + fprintf(stderr, "%s: no longer a special file\n", + name); + do_compare_error; + skipfile(); + return; + } + + if (sb.st_rdev != (dev_t)curfile.dip->di_rdev) { + fprintf(stderr, + "%s: device changed from %d,%d to %d,%d.\n", + name, + major(curfile.dip->di_rdev), + minor(curfile.dip->di_rdev), + major(sb.st_rdev), + minor(sb.st_rdev)); + do_compare_error; + } + skipfile(); + return; + + case IFREG: +#if COMPARE_ONTHEFLY + if ((ifile = OPEN(name, O_RDONLY)) < 0) { + panic("Can't open %s: %s\n", name, strerror(errno)); + skipfile(); + do_compare_error; + } + else { + cmperror = 0; + getfile(xtrcmpfile, xtrcmpskip); + if (!cmperror) { + char c; + if (read(ifile, &c, 1) != 0) { + fprintf(stderr, "%s: size has changed.\n", + name); + cmperror = 1; + } + } + if (cmperror) + do_compare_error; + close(ifile); + } +#else + if (tmpfile == NULL) { + /* argument to mktemp() must not be in RO space: */ + snprintf(tmpfilename, sizeof(tmpfilename), "%s/restoreCXXXXXX", tmpdir); + tmpfile = mktemp(&tmpfilename[0]); + } + if ((STAT(tmpfile, &stemp) == 0) && (unlink(tmpfile) != 0)) { + panic("cannot delete tmp file %s: %s\n", + tmpfile, strerror(errno)); + } + if ((ofile = OPEN(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { + panic("cannot create file temp file %s: %s\n", + name, strerror(errno)); + } + getfile(xtrfile, xtrskip); + (void) close(ofile); +#ifdef COMPARE_FAIL_KEEP_FILE + if (cmpfiles(tmpfile, name, &sb)) + unlink(tmpfile); +#else + cmpfiles(tmpfile, name, &sb); + unlink(tmpfile); +#endif +#endif /* COMPARE_ONTHEFLY */ + return; + } + /* NOTREACHED */ +} + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) +static void (*readtape_func)(char *) = readtape_set; + +/* + * Read TP_BSIZE blocks from the input. + * Handle read errors, and end of media. + * Decompress compressed blocks. + */ +static void +readtape(char *buf) +{ + (*readtape_func)(buf); /* call the actual processing routine */ +} + +/* + * Set function pointer for readtape() routine. zflag and magtapein must + * be correctly set before the first call to readtape(). + */ +static void +readtape_set(char *buf) +{ + if (!zflag) + readtape_func = readtape_uncompr; + else { + newcomprbuf(ntrec); + if (magtapein) + readtape_func = readtape_comprtape; + else + readtape_func = readtape_comprfile; + } + readtape(buf); +} + +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + +/* + * This is the original readtape(), it's used for reading uncompressed input. + * Read TP_BSIZE blocks from the input. + * Handle read errors, and end of media. + */ +static void +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) +readtape_uncompr(char *buf) +#else +readtape(char *buf) +#endif +{ + ssize_t rd, newvol, i; + int cnt, seek_failed; + + if (blkcnt < numtrec) { + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; + return; + } + tbufptr = tapebuf; + for (i = 0; i < ntrec; i++) + ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; + if (numtrec == 0) + numtrec = ntrec; + cnt = ntrec * TP_BSIZE; + rd = 0; +#ifdef USE_QFA + if (createtapeposflag) + (void)GetTapePos(&curtapepos); +#endif +getmore: +#ifdef RRESTORE + if (!Afile && host) + i = rmtread(&tapebuf[rd], cnt); + else +#endif + i = read(mt, &tapebuf[rd], cnt); + + /* + * Check for mid-tape short read error. + * If found, skip rest of buffer and start with the next. + */ + if (!pipein && numtrec < ntrec && i > 0) { + Dprintf(stdout, "mid-media short read error.\n"); + numtrec = ntrec; + } + /* + * Handle partial block read. + */ + if (pipein && i == 0 && rd > 0) + i = rd; + else if (i > 0 && i != ntrec * TP_BSIZE) { + if (pipein) { + rd += i; + cnt -= i; + if (cnt > 0) + goto getmore; + i = rd; + } else { + /* + * Short read. Process the blocks read. + */ + if (i % TP_BSIZE != 0) + Vprintf(stdout, + "partial block read: %ld should be %ld\n", + (long)i, ntrec * TP_BSIZE); + numtrec = i / TP_BSIZE; + } + } + /* + * Handle read error. + */ + if (i < 0) { + fprintf(stderr, "Tape read error while "); + switch (curfile.action) { + default: + fprintf(stderr, "trying to set up tape\n"); + break; + case UNKNOWN: + fprintf(stderr, "trying to resynchronize\n"); + break; + case USING: + fprintf(stderr, "restoring %s\n", curfile.name); + break; + case SKIP: + fprintf(stderr, "skipping over inode %lu\n", + (unsigned long)curfile.ino); + break; + } + if (!yflag && !reply("continue")) + exit(1); + i = ntrec * TP_BSIZE; + memset(tapebuf, 0, (size_t)i); +#ifdef RRESTORE + if (!Afile && host) + seek_failed = (rmtseek(i, 1) < 0); + else +#endif + seek_failed = (LSEEK(mt, i, SEEK_CUR) == (OFF_T)-1); + + if (seek_failed) { + warn("continuation failed"); + if (!yflag && !reply("assume end-of-tape and continue")) + exit(1); + i = 0; + } + } + /* + * Handle end of tape. + */ + if (i == 0) { + Vprintf(stdout, "End-of-tape encountered\n"); + if (!pipein) { + newvol = volno + 1; + volno = 0; + numtrec = 0; + getvol(newvol); + readtape(buf); + return; + } + if (rd % TP_BSIZE != 0) + panic("partial block read: %d should be %d\n", + rd, ntrec * TP_BSIZE); + terminateinput(); + memmove(&tapebuf[rd], &endoftapemark, TP_BSIZE); + } + blkcnt = 0; + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; +} + +#if defined(HAVE_ZLIB) || defined(HAVE_BZLIB) || defined(HAVE_LZO) + +/* + * Read a compressed format block from a file or pipe and uncompress it. + * Attempt to handle read errors, and end of file. + */ +static void +readtape_comprfile(char *buf) +{ + long rl, size, i, ret; + int newvol; + struct tapebuf *tpb; + + if (blkcnt < numtrec) { + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; + return; + } + /* need to read the next block */ + tbufptr = tapebuf; + for (i = 0; i < ntrec; i++) + ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; + numtrec = ntrec; + tpb = (struct tapebuf *) tapebuf; + + /* read the block prefix */ + ret = read_a_block(mt, tapebuf, PREFIXSIZE, &rl); + converttapebuf(tpb); + + if (Vflag && (ret == 0 || rl < (int)PREFIXSIZE || tpb->length == 0)) + ret = 0; + if (ret <= 0) + goto readerr; + + /* read the data */ + size = tpb->length; + if (size > bufsize) { + /* something's wrong */ + Vprintf(stdout, "Prefix size error, max size %d, got %ld\n", + bufsize, size); + size = bufsize; + tpb->length = bufsize; + } + ret = read_a_block(mt, tpb->buf, size, &rl); + if (ret <= 0) + goto readerr; + + tbufptr = decompress_tapebuf(tpb, rl + PREFIXSIZE); + if (tbufptr == NULL) { + msg_read_error("File decompression error while"); + if (!yflag && !reply("continue")) + exit(1); + memset(tapebuf, 0, bufsize); + tbufptr = tapebuf; + } + + blkcnt = 0; + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; + return; + +readerr: + /* Errors while reading from a file or pipe are catastrophic. Since + * there are no block boundaries, it's impossible to bypass the + * block in error and find the start of the next block. + */ + if (ret == 0) { + /* It's possible to have multiple input files using -M + * and -f file1,file2... + */ + Vprintf(stdout, "End-of-File encountered\n"); + if (!pipein) { + newvol = volno + 1; + volno = 0; + numtrec = 0; + getvol(newvol); + readtape(buf); + return; + } + } + msg_read_error("Read error while"); + /* if (!yflag && !reply("continue")) */ + exit(1); +} + +/* + * Read compressed data from a tape and uncompress it. + * Handle read errors, and end of media. + * Since a tape consists of separate physical blocks, we try + * to recover from errors by repositioning the tape to the next + * block. + */ +static void +readtape_comprtape(char *buf) +{ + long rl, size, i; + int ret, newvol; + struct tapebuf *tpb; + struct mtop tcom; + + if (blkcnt < numtrec) { + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; + return; + } + /* need to read the next block */ + tbufptr = tapebuf; + for (i = 0; i < ntrec; i++) + ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; + numtrec = ntrec; + tpb = (struct tapebuf *) tapebuf; + + /* read the block */ + size = bufsize + PREFIXSIZE; + ret = read_a_block(mt, tapebuf, size, &rl); + if (ret <= 0) + goto readerr; + + converttapebuf(tpb); + tbufptr = decompress_tapebuf(tpb, rl); + if (tbufptr == NULL) { + msg_read_error("Tape decompression error while"); + if (!yflag && !reply("continue")) + exit(1); + memset(tapebuf, 0, PREFIXSIZE + bufsize); + tbufptr = tapebuf; + } + goto moverecord; + +readerr: + /* Handle errors: EOT switches to the next volume, other errors + * attempt to position the tape to the next block. + */ + if (ret == 0) { + Vprintf(stdout, "End-of-tape encountered\n"); + newvol = volno + 1; + volno = 0; + numtrec = 0; + getvol(newvol); + readtape(buf); + return; + } + + msg_read_error("Tape read error while"); + if (!yflag && !reply("continue")) + exit(1); + memset(tapebuf, 0, PREFIXSIZE + bufsize); + tbufptr = tapebuf; + +#ifdef RRESTORE + if (host) + rl = rmtioctl(MTFSR, 1); + else +#endif + { + tcom.mt_op = MTFSR; + tcom.mt_count = 1; + rl = ioctl(mt, MTIOCTOP, &tcom); + } + + if (rl < 0) { + warn("continuation failed"); + if (!yflag && !reply("assume end-of-tape and continue")) + exit(1); + ret = 0; /* end of tape */ + goto readerr; + } + +moverecord: + blkcnt = 0; + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + blksread++; + tpblksread++; +} + +/* + * Decompress a struct tapebuf into a buffer. readsize is the size read + * from the tape/file and is used for error messages. Returns a pointer + * to the location of the uncompressed buffer or NULL on errors. + * Adjust numtrec and complain for a short block. + */ +static char * +decompress_tapebuf(struct tapebuf *tpbin, int readsize) +{ + /* If zflag is on, all blocks have a struct tapebuf prefix */ + /* zflag gets set in setup() from the dump header */ + int cresult, blocklen; + unsigned long worklen; + char *output = NULL,*reason = NULL, *lengtherr = NULL; + + /* build a length error message */ + blocklen = tpbin->length; + if (readsize < blocklen + (int)PREFIXSIZE) + lengtherr = "short"; + else + if (readsize > blocklen + (int)PREFIXSIZE) + lengtherr = "long"; + + worklen = comprlen; + cresult = 1; + if (tpbin->compressed) { + /* uncompress whatever we read, if it fails, complain later */ + if (tpbin->flags == COMPRESS_ZLIB) { +#ifndef HAVE_ZLIB + errx(1,"This restore version doesn't support zlib decompression"); +#else + cresult = uncompress(comprbuf, &worklen, + tpbin->buf, blocklen); + output = comprbuf; + switch (cresult) { + case Z_OK: + break; + case Z_MEM_ERROR: + reason = "not enough memory"; + break; + case Z_BUF_ERROR: + reason = "buffer too small"; + break; + case Z_DATA_ERROR: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == Z_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_ZLIB */ + } + if (tpbin->flags == COMPRESS_BZLIB) { +#ifndef HAVE_BZLIB + errx(1,"This restore version doesn't support bzlib decompression"); +#else + unsigned int worklen2 = worklen; + cresult = BZ2_bzBuffToBuffDecompress( + comprbuf, &worklen2, + tpbin->buf, blocklen, 0, 0); + worklen = worklen2; + output = comprbuf; + switch (cresult) { + case BZ_OK: + break; + case BZ_MEM_ERROR: + reason = "not enough memory"; + break; + case BZ_OUTBUFF_FULL: + reason = "buffer too small"; + break; + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + case BZ_UNEXPECTED_EOF: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == BZ_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_BZLIB */ + } + if (tpbin->flags == COMPRESS_LZO) { +#ifndef HAVE_LZO + errx(1,"This restore version doesn't support lzo decompression"); +#else + lzo_uint worklen2 = worklen; + cresult = lzo1x_decompress(tpbin->buf, blocklen, + comprbuf, &worklen2, NULL); + worklen = worklen2; + output = comprbuf; + switch (cresult) { + case LZO_E_OK: + break; + case LZO_E_ERROR: + case LZO_E_EOF_NOT_FOUND: + reason = "data error"; + break; + default: + reason = "unknown"; + } + if (cresult == LZO_E_OK) + cresult = 1; + else + cresult = 0; +#endif /* HAVE_LZO */ + } + } + else { + output = tpbin->buf; + worklen = blocklen; + } + if (cresult) { + numtrec = worklen / TP_BSIZE; + if (worklen % TP_BSIZE != 0) + reason = "length mismatch"; + } + if (reason) { + if (lengtherr) + fprintf(stderr, "%s compressed block: %d expected: %u\n", + lengtherr, readsize, tpbin->length + PREFIXSIZE); + fprintf(stderr, "decompression error, block %ld: %s\n", + tpblksread+1, reason); + if (!cresult) + output = NULL; + } + return output; +} + +/* + * Print an error message for a read error. + * This was exteracted from the original readtape(). + */ +static void +msg_read_error(char *m) +{ + switch (curfile.action) { + default: + fprintf(stderr, "%s trying to set up tape\n", m); + break; + case UNKNOWN: + fprintf(stderr, "%s trying to resynchronize\n", m); + break; + case USING: + fprintf(stderr, "%s restoring %s\n", m, curfile.name); + break; + case SKIP: + fprintf(stderr, "%s skipping over inode %lu\n", m, + (unsigned long)curfile.ino); + break; + } +} +#endif /* HAVE_ZLIB || HAVE_BZLIB || HAVE_LZO */ + +/* + * Read the first block and get the blocksize from it. Test + * for a compressed dump tape/file. setup() will make the final + * determination by checking the compressed flag if gethead() + * finds a valid header. The test here is necessary to offset the buffer + * by the size of the compressed prefix. zflag is set here so that + * readtape_set can set the correct function pointer for readtape(). + * Note that the first block of each tape/file is not compressed + * and does not have a prefix. + */ +static void +findtapeblksize(void) +{ + long i; + size_t len; + struct tapebuf *tpb = (struct tapebuf *) tapebuf; + struct s_spcl spclpt; + + for (i = 0; i < ntrec; i++) + ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; + blkcnt = 0; + tbufptr = tapebuf; + /* + * For a pipe or file, read in the first record. For a tape, read + * the first block. + */ + len = magtapein ? ntrec * TP_BSIZE : TP_BSIZE; + + if (read_a_block(mt, tapebuf, len, &i) <= 0) + errx(1, "Tape read error on first record"); + + memcpy(&spclpt, tapebuf, TP_BSIZE); + if (converthead(&spclpt) == FAIL) { + cvtflag++; + if (converthead(&spclpt) == FAIL) { + /* Special case for old compressed tapes with prefix */ + if (magtapein && (i % TP_BSIZE != 0)) + goto oldformat; + errx(1, "Tape is not a dump tape"); + } + fprintf(stderr, "Converting to new file system format.\n"); + } + /* + * If the input is from a file or a pipe, we read TP_BSIZE + * bytes looking for a dump header. If the dump is compressed + * we need to read in the rest of the block, as determined + * by c_ntrec in the dump header. The first block of the + * dump is not compressed and does not have a prefix. + */ + if (!magtapein) { + if (spclpt.c_type == TS_TAPE + && spclpt.c_flags & DR_COMPRESSED) { + /* It's a compressed dump file, read in the */ + /* rest of the block based on spclpt.c_ntrec. */ + if (spclpt.c_ntrec > ntrec) + errx(1, "Tape blocksize is too large, use " + "\'-b %d\' ", spclpt.c_ntrec); + ntrec = spclpt.c_ntrec; + len = (ntrec - 1) * TP_BSIZE; + zflag = 1; + } + else { + /* read in the rest of the block based on bufsize */ + len = bufsize - TP_BSIZE; + } + if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) < 0 + || (i != (long)len && i % TP_BSIZE != 0)) + errx(1,"Error reading dump file header"); + tbufptr = tapebuf; + numtrec = ntrec; + Vprintf(stdout, "Input block size is %ld\n", ntrec); + return; + } /* if (!magtapein) */ + + /* + * If the input is a tape, we tried to read ntrec * TP_BSIZE bytes. + * If the value of ntrec is too large, we read less than + * what we asked for; adjust the value of ntrec and test for + * a compressed dump tape. + */ + if (i % TP_BSIZE != 0) { +oldformat: + /* may be old format compressed dump tape with a prefix */ + memcpy(&spclpt, tpb->buf, TP_BSIZE); + cvtflag = 0; + if (converthead(&spclpt) == FAIL) { + cvtflag++; + if (converthead(&spclpt) == FAIL) + errx(1, "Tape is not a dump tape"); + fprintf(stderr, "Converting to new file system format.\n"); + } + if (i % TP_BSIZE == PREFIXSIZE + && tpb->compressed == 0 + && spclpt.c_type == TS_TAPE + && spclpt.c_flags & DR_COMPRESSED) { + zflag = 1; + tbufptr = tpb->buf; + if (tpb->length > bufsize) + errx(1, "Tape blocksize is too large, use " + "\'-b %d\' ", tpb->length / TP_BSIZE); + } + else + errx(1, "Tape block size (%ld) is not a multiple of dump block size (%d)", + i, TP_BSIZE); + } + ntrec = i / TP_BSIZE; + if (spclpt.c_type == TS_TAPE) { + if (spclpt.c_flags & DR_COMPRESSED) + zflag = 1; + if (spclpt.c_ntrec > ntrec) + errx(1, "Tape blocksize is too large, use " + "\'-b %d\' ", spclpt.c_ntrec); + } + numtrec = ntrec; + Vprintf(stdout, "Tape block size is %ld\n", ntrec); +} + +/* + * Read a block of data handling all of the messy details. + */ +static int read_a_block(int fd, char *buf, size_t len, long *lengthread) +{ + long i = 1, size; + + size = len; + while (size > 0) { +#ifdef RRESTORE + if (!Afile && host) + i = rmtread(buf, size); + else +#endif + i = read(fd, buf, size); + + if (i <= 0) + break; /* EOD or error */ + size -= i; + if (magtapein) + break; /* block at a time for mt */ + buf += i; + } + *lengthread = len - size; + return i; +} + +void +closemt(void) +{ + + if (mt < 0) + return; +#ifdef RRESTORE + if (!Afile && host) + rmtclose(); + else +#endif + (void) close(mt); +} + +static void +setmagtapein(void) { + struct mtget mt_stat; + static int done = 0; + if (done) + return; + done = 1; + if (!pipein) { + /* need to know if input is really from a tape */ +#ifdef RRESTORE + if (host) + magtapein = !lflag; + else +#endif + magtapein = ioctl(mt, MTIOCGET, (char *)&mt_stat) == 0; + } + + Vprintf(stdout,"Input is from a %s %s\n", + host ? "remote" : "local", + magtapein ? "tape" : + Vflag ? "multi-volume (no tape)" : "file/pipe"); +} + +/* + * Read the next block from the tape. + * Check to see if it is one of several vintage headers. + * If it is an old style header, convert it to a new style header. + * If it is not any valid header, return an error. + */ +static int +gethead(struct s_spcl *buf) +{ + readtape((char *)buf); + return converthead(buf); +} + +static int +converthead(struct s_spcl *buf) +{ + int32_t i; + union { + quad_t qval; + int32_t val[2]; + } qcvt; + union u_ospcl { + char dummy[TP_BSIZE]; + struct s_ospcl { + int32_t c_type; + int32_t c_date; + int32_t c_ddate; + int32_t c_volume; + int32_t c_tapea; + u_int16_t c_inumber; + int32_t c_magic; + int32_t c_checksum; + struct odinode { + u_int16_t odi_mode; + u_int16_t odi_nlink; + u_int16_t odi_uid; + u_int16_t odi_gid; + int32_t odi_size; + int32_t odi_rdev; + char odi_addr[36]; + int32_t odi_atime; + int32_t odi_mtime; + int32_t odi_ctime; + } c_dinode; + int32_t c_count; + char c_fill[256]; + } s_ospcl; + } u_ospcl; + + if (!cvtflag) { + if (buf->c_magic != NFS_MAGIC) { + if (swabi(buf->c_magic) != NFS_MAGIC) + return (FAIL); + if (!Bcvt) { + Vprintf(stdout, "Note: Doing Byte swapping\n"); + Bcvt = 1; + } + } + if (checksum((int *)buf) == FAIL) + return (FAIL); + if (Bcvt) + swabst((u_char *)"8i4s31i528bi192b3i", (u_char *)buf); + goto good; + } + memcpy(&u_ospcl.s_ospcl, buf, TP_BSIZE); + if (checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) + return(FAIL); + if (u_ospcl.s_ospcl.c_magic == OFS_MAGIC) { + memset((char *)buf, 0, (long)TP_BSIZE); + buf->c_type = u_ospcl.s_ospcl.c_type; + buf->c_date = u_ospcl.s_ospcl.c_date; + buf->c_ddate = u_ospcl.s_ospcl.c_ddate; + buf->c_volume = u_ospcl.s_ospcl.c_volume; + buf->c_tapea = u_ospcl.s_ospcl.c_tapea; + buf->c_inumber = u_ospcl.s_ospcl.c_inumber; + buf->c_checksum = u_ospcl.s_ospcl.c_checksum; + buf->c_magic = u_ospcl.s_ospcl.c_magic; + buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; + buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; + buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; + buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; + buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; + buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; +#if defined(__linux__) || defined(sunos) + buf->c_dinode.di_atime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_atime; + buf->c_dinode.di_mtime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime; + buf->c_dinode.di_ctime.tv_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime; +#else /* __linux__ || sunos */ + buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; + buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; + buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; +#endif /* __linux__ || sunos */ + buf->c_count = u_ospcl.s_ospcl.c_count; + memmove(buf->c_addr, u_ospcl.s_ospcl.c_fill, (long)256); + } + else if (u_ospcl.s_ospcl.c_magic == FS_UFS2_MAGIC) { + buf->c_date = (int32_t)(*(int64_t *)&u_ospcl.dummy[896]); + buf->c_ddate = (int32_t)(*(int64_t *)&u_ospcl.dummy[904]); + buf->c_tapea = (int32_t)(*(int64_t *)&u_ospcl.dummy[912]); + buf->c_firstrec = (int32_t)(*(int64_t *)&u_ospcl.dummy[920]); + buf->c_ntrec = 0; + buf->c_extattributes = 0; + buf->c_flags |= DR_NEWINODEFMT; + ufs2flag = 1; + } + else + return(FAIL); + buf->c_magic = NFS_MAGIC; + +good: + if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && + (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { + qcvt.qval = buf->c_dinode.di_size; + if (qcvt.val[0] || qcvt.val[1]) { + Vprintf(stdout, "Note: Doing Quad swapping\n"); + Qcvt = 1; + } + } + if (Qcvt) { + qcvt.qval = buf->c_dinode.di_size; + i = qcvt.val[1]; + qcvt.val[1] = qcvt.val[0]; + qcvt.val[0] = i; + buf->c_dinode.di_size = qcvt.qval; + } + readmapflag = 0; + + switch (buf->c_type) { + + case TS_CLRI: + case TS_BITS: + /* + * Have to patch up missing information in bit map headers + */ + buf->c_inumber = 0; + buf->c_dinode.di_size = buf->c_count * TP_BSIZE; + if (buf->c_count > TP_NINDIR) + readmapflag = 1; + else + for (i = 0; i < buf->c_count; i++) + buf->c_addr[i]++; + break; + + case TS_TAPE: + if ((buf->c_flags & DR_NEWINODEFMT) == 0) + oldinofmt = 1; + /* fall through */ + case TS_END: + buf->c_inumber = 0; + if (buf->c_flags & DR_INODEINFO) { + memcpy(volinfo, buf->c_inos, TP_NINOS * sizeof(dump_ino_t)); + if (Bcvt) + swabst((u_char *)"128i", (u_char *)volinfo); + } + break; + + case TS_INODE: + case TS_ADDR: + break; + + default: + panic("gethead: unknown inode type %d\n", buf->c_type); + break; + } + /* + * If we are restoring a filesystem with old format inodes, + * copy the uid/gid to the new location. + */ + if (oldinofmt) { + buf->c_dinode.di_uid = buf->c_dinode.di_ouid; + buf->c_dinode.di_gid = buf->c_dinode.di_ogid; + } + if (dflag) + accthdr(buf); + return(GOOD); +} + +static void +converttapebuf(struct tapebuf *tpb) +{ + if (Bcvt) { + struct tb { + unsigned int length:28; + unsigned int flags:3; + unsigned int compressed:1; + } tb; + swabst((u_char *)"i", (u_char *)tpb); + memcpy(&tb, tpb, 4); + tpb->length = tb.length; + tpb->flags = tb.flags; + tpb->compressed = tb.compressed; + } +} + +/* + * Check that a header is where it belongs and predict the next header + */ +static void +accthdr(struct s_spcl *header) +{ + static dump_ino_t previno = 0x7fffffff; + static int prevtype; + static long predict; + long blks, i; + + if (header->c_type == TS_TAPE) { + fprintf(stderr, "Volume header (%s inode format) ", + oldinofmt ? "old" : "new"); + if (header->c_firstrec) + fprintf(stderr, "begins with record %d", + header->c_firstrec); + fprintf(stderr, "\n"); + previno = 0x7fffffff; + return; + } + if (previno == 0x7fffffff) + goto newcalc; + switch (prevtype) { + case TS_BITS: + fprintf(stderr, "Dumped inodes map header"); + break; + case TS_CLRI: + fprintf(stderr, "Used inodes map header"); + break; + case TS_INODE: + fprintf(stderr, "File header, ino %lu", (unsigned long)previno); + break; + case TS_ADDR: + fprintf(stderr, "File continuation header, ino %ld", (long)previno); + break; + case TS_END: + fprintf(stderr, "End of tape header"); + break; + } + if (predict != blksread - 1) + fprintf(stderr, "; predicted %ld blocks, got %ld blocks", + predict, blksread - 1); + fprintf(stderr, "\n"); +newcalc: + blks = 0; + if (header->c_type != TS_END) + for (i = 0; i < header->c_count; i++) + if (readmapflag || header->c_addr[i] != 0) + blks++; + predict = blks; + blksread = 0; + prevtype = header->c_type; + previno = header->c_inumber; +} + +/* + * Find an inode header. + * Complain if had to skip, and complain is set. + */ +static void +findinode(struct s_spcl *header) +{ + static long skipcnt = 0; + long i; + char buf[TP_BSIZE]; + + curfile.name = ""; + curfile.action = UNKNOWN; + curfile.dip = NULL; + curfile.ino = 0; + do { + if (header->c_magic != NFS_MAGIC) { + skipcnt++; + while (gethead(header) == FAIL || + header->c_date != dumpdate) + skipcnt++; + } + switch (header->c_type) { + + case TS_ADDR: + /* + * Skip up to the beginning of the next record + */ + for (i = 0; i < header->c_count; i++) + if (header->c_addr[i]) + readtape(buf); + while (gethead(header) == FAIL || + header->c_date != dumpdate) + skipcnt++; + break; + + case TS_INODE: + curfile.dip = &header->c_dinode; + curfile.ino = header->c_inumber; + break; + + case TS_END: + curfile.ino = maxino; + break; + + case TS_CLRI: + curfile.name = ""; + break; + + case TS_BITS: + curfile.name = ""; + break; + + case TS_TAPE: + panic("unexpected tape header\n"); + /* NOTREACHED */ + + default: + panic("unknown tape header type %d\n", spcl.c_type); + /* NOTREACHED */ + + } + } while (header->c_type == TS_ADDR); + if (skipcnt > 0) +#ifdef USE_QFA + if (!noresyncmesg) +#endif + fprintf(stderr, "resync restore, skipped %ld blocks\n", + skipcnt); + skipcnt = 0; +} + +static int +checksum(int *buf) +{ + int i, j; + + j = sizeof(union u_spcl) / sizeof(int); + i = 0; + if(!Bcvt) { + do + i += *buf++; + while (--j); + } else { + /* What happens if we want to read restore tapes + for a 16bit int machine??? */ + do + i += swabi(*buf++); + while (--j); + } + + if (i != CHECKSUM) { + fprintf(stderr, "Checksum error %o, inode %lu file %s\n", i, + (unsigned long)curfile.ino, curfile.name); + return(FAIL); + } + return(GOOD); +} + +#ifdef RRESTORE +#ifdef __STDC__ +#include +#else +#include +#endif + +void +#ifdef __STDC__ +msg(const char *fmt, ...) +#else +msg(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)vfprintf(stderr, fmt, ap); + va_end(ap); +} +#endif /* RRESTORE */ + +static u_char * +swab16(u_char *sp, int n) +{ + char c; + + while (--n >= 0) { + c = sp[0]; sp[0] = sp[1]; sp[1] = c; + sp += 2; + } + return (sp); +} + +static u_char * +swab32(u_char *sp, int n) +{ + char c; + + while (--n >= 0) { + c = sp[0]; sp[0] = sp[3]; sp[3] = c; + c = sp[1]; sp[1] = sp[2]; sp[2] = c; + sp += 4; + } + return (sp); +} + +static u_char * +swab64(u_char *sp, int n) +{ + char c; + + while (--n >= 0) { + c = sp[0]; sp[0] = sp[7]; sp[7] = c; + c = sp[1]; sp[1] = sp[6]; sp[6] = c; + c = sp[2]; sp[2] = sp[5]; sp[5] = c; + c = sp[3]; sp[3] = sp[4]; sp[4] = c; + sp += 8; + } + return (sp); +} + +void +swabst(u_char *cp, u_char *sp) +{ + int n = 0; + + while (*cp) { + switch (*cp) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = (n * 10) + (*cp++ - '0'); + continue; + + case 's': case 'w': case 'h': + if (n == 0) + n = 1; + sp = swab16(sp, n); + break; + + case 'i': + if (n == 0) + n = 1; + sp = swab32(sp, n); + break; + + case 'l': + if (n == 0) + n = 1; + sp = swab64(sp, n); + break; + + default: /* Any other character, like 'b' counts as byte. */ + if (n == 0) + n = 1; + sp += n; + break; + } + cp++; + n = 0; + } +} + +static u_int +swabi(u_int x) +{ + swabst((u_char *)"i", (u_char *)&x); + return (x); +} + +#if 0 +static u_long +swabl(u_long x) +{ + swabst((u_char *)"l", (u_char *)&x); + return (x); +} +#endif + +void +RequestVol(long tnum) +{ + FLUSHTAPEBUF(); + getvol(tnum); +} + +#ifdef USE_QFA +#ifdef sunos +extern int fdsmtc; + +struct uscsi_cmd { + int uscsi_flags; /* read, write, etc. see below */ + short uscsi_status; /* resulting status */ + short uscsi_timeout; /* Command Timeout */ + caddr_t uscsi_cdb; /* cdb to send to target */ + caddr_t uscsi_bufaddr; /* i/o source/destination */ + u_int uscsi_buflen; /* size of i/o to take place */ + u_int uscsi_resid; /* resid from i/o operation */ + u_char uscsi_cdblen; /* # of valid cdb bytes */ + u_char uscsi_rqlen; /* size of uscsi_rqbuf */ + u_char uscsi_rqstatus; /* status of request sense cmd */ + u_char uscsi_rqresid; /* resid of request sense cmd */ + caddr_t uscsi_rqbuf; /* request sense buffer */ + void *uscsi_reserved_5; /* Reserved for Future Use */ +}; + +#define CDB_GROUP0 6 /* 6-byte cdb's */ +#define CDB_GROUP1 10 /* 10-byte cdb's */ +#define CDB_GROUP2 10 /* 10-byte cdb's */ +#define CDB_GROUP3 0 /* reserved */ +#define CDB_GROUP4 16 /* 16-byte cdb's */ +#define CDB_GROUP5 12 /* 12-byte cdb's */ +#define CDB_GROUP6 0 /* reserved */ +#define CDB_GROUP7 0 /* reserved */ + +#define USCSI_WRITE 0x00000 /* send data to device */ +#define USCSI_SILENT 0x00001 /* no error messages */ +#define USCSI_DIAGNOSE 0x00002 /* fail if any error occurs */ +#define USCSI_ISOLATE 0x00004 /* isolate from normal commands */ +#define USCSI_READ 0x00008 /* get data from device */ +#define USCSI_RESET 0x04000 /* Reset target */ +#define USCSI_RESET_ALL 0x08000 /* Reset all targets */ +#define USCSI_RQENABLE 0x10000 /* Enable Request Sense extensions */ + +#define USCSIIOC (0x04 << 8) +#define USCSICMD (USCSIIOC|201) /* user scsi command */ + +#define USCSI_TIMEOUT 30 +#define USCSI_SHORT_TIMEOUT 900 +#define USCSI_LONG_TIMEOUT 14000 + +#define B(s,i) ((unsigned char)((s) >> i)) +#define B1(s) ((unsigned char)(s)) + +#define MSB4(s,v) *(s)=B(v,24),(s)[1]=B(v,16), (s)[2]=B(v,8), (s)[3]=B1(v) + + +int +GetTapePos(long long *pos) +{ + int err = 0; + struct uscsi_cmd scmd; + char buf[512]; + char parm[512 * 8]; + long lpos; + + (void)memset((void *)buf, 0, sizeof(buf)); + (void)memset((void *)&scmd, 0, sizeof(scmd)); + scmd.uscsi_flags = USCSI_READ|USCSI_SILENT; + scmd.uscsi_timeout = USCSI_TIMEOUT; + scmd.uscsi_cdb = buf; + scmd.uscsi_cdblen = CDB_GROUP1; + buf[0] = 0x34; /* read position */ + buf[1] = 0; + (void)memset((void *)parm, 0, 512); + scmd.uscsi_bufaddr = parm; + scmd.uscsi_buflen = 56; + if (ioctl(fdsmtc, USCSICMD, &scmd) == -1) { + err = errno; + return err; + } + (void)memcpy(&lpos, &parm[4], sizeof(long)); + *pos = lpos; + return err; +} + +int +GotoTapePos(long long pos) +{ + int err = 0; + struct uscsi_cmd scmd; + char buf[512]; + char parm[512 * 8]; + long lpos = (long)pos; + + (void)memset((void *)buf, 0, sizeof(buf)); + (void)memset((void *)&scmd, 0, sizeof(scmd)); + scmd.uscsi_flags = USCSI_WRITE|USCSI_SILENT; + scmd.uscsi_timeout = 360; /* 5 Minutes */ + scmd.uscsi_cdb = buf; + scmd.uscsi_cdblen = CDB_GROUP1; + buf[0] = 0x2b; /* locate */ + buf[1] = 0; + MSB4(&buf[3], lpos); + (void)memset((void *)parm, 0, 512); + scmd.uscsi_bufaddr = NULL; + scmd.uscsi_buflen = 0; + if (ioctl(fdsmtc, USCSICMD, &scmd) == -1) { + err = errno; + return err; + } + return err; +} +#endif + +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 + +#ifdef __linux__ +typedef struct mt_pos { + short mt_op; + int mt_count; +} MTPosRec, *MTPosPtr; + + +/* + * get the current position of the tape + */ +int +GetTapePos(long long *pos) +{ + int err = 0; + +#ifdef RDUMP + if (host) { + *pos = (long long) rmtseek((OFF_T)0, (int)LSEEK_GET_TAPEPOS); + err = *pos < 0; + } + else +#endif + { + if (magtapein) { + long mtpos; + *pos = 0; + err = (ioctl(mt, MTIOCPOS, &mtpos) < 0); + *pos = (long long)mtpos; + } + else { + *pos = LSEEK(mt, 0, SEEK_CUR); + err = (*pos < 0); + } + } + if (err) { + err = errno; + fprintf(stdout, "[%ld] error: %d (getting tapepos: %lld)\n", + (unsigned long)getpid(), err, *pos); + return err; + } + return err; +} + +/* + * go to specified position on tape + */ +int +GotoTapePos(long long pos) +{ + int err = 0; + +#ifdef RDUMP + if (host) + err = (rmtseek((OFF_T)pos, (int)LSEEK_GO2_TAPEPOS) < 0); + else +#endif + { + if (magtapein) { + struct mt_pos buf; + buf.mt_op = MTSEEK; + buf.mt_count = (int) pos; + err = (ioctl(mt, MTIOCTOP, &buf) < 0); + } + else { + pos = LSEEK(mt, pos, SEEK_SET); + err = (pos < 0); + } + } + if (err) { + err = errno; + fprintf(stdout, "[%ld] error: %d (setting tapepos: %lld)\n", + (unsigned long)getpid(), err, pos); + return err; + } + return err; +} +#endif /* __linux__ */ + +/* + * read next data from tape to re-sync + */ +void +ReReadFromTape(void) +{ + FLUSHTAPEBUF(); + noresyncmesg = 1; + if (gethead(&spcl) == FAIL) { +#ifdef DEBUG_QFA + fprintf(stdout, "DEBUG 1 gethead failed\n"); +#endif + } + findinode(&spcl); + noresyncmesg = 0; +} + +void +ReReadInodeFromTape(dump_ino_t theino) +{ + long cntloop = 0; + + FLUSHTAPEBUF(); + noresyncmesg = 1; + do { + cntloop++; + gethead(&spcl); + } while (!(spcl.c_inumber == theino && spcl.c_type == TS_INODE && spcl.c_date == dumpdate)); +#ifdef DEBUG_QFA + fprintf(stderr, "DEBUG: %ld reads\n", cntloop); + fprintf(stderr, "DEBUG: bufsize %ld\n", bufsize); + fprintf(stderr, "DEBUG: ntrec %ld\n", ntrec); + fprintf(stderr, "DEBUG: %ld reads\n", cntloop); +#endif + findinode(&spcl); + noresyncmesg = 0; +} + +#ifdef sunos +int +OpenSMTCmt(char *themagtape) +{ + if (GetSCSIIDFromPath(themagtape, &scsiid)) { + fprintf(stderr, "can't get SCSI-ID for %s\n", themagtape); + return -1; + } + if (scsiid < 0) { + fprintf(stderr, "can't get SCSI-ID for %s\n", themagtape); + return -1; + } + sprintf(smtcpath, "/dev/rsmtc%ld,0", scsiid); + if ((fdsmtc = open(smtcpath, O_RDWR)) == -1) { + fprintf(stderr, "can't open smtc device: %s, %d\n", smtcpath, errno); + return -1; + } + return 0; +} +#endif /* sunos */ +#endif /* USE_QFA */ diff --git a/restore/utilities.c b/restore/utilities.c new file mode 100644 index 0000000..e0db9af --- /dev/null +++ b/restore/utilities.c @@ -0,0 +1,720 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: utilities.c,v 1.24 2003/11/22 16:52:16 stelian Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __linux__ +#include +#include +#include +#ifdef HAVE_EXT2FS_EXT2_FS_H +#include +#else +#include +#endif +#include +#include +#else /* __linux__ */ +#ifdef sunos +#include +#include +#include +#else +#include +#include +#endif +#endif /* __linux__ */ +#ifdef DUMP_MACOSX +#include "darwin.h" +#endif +#include "restore.h" +#include "extern.h" + +/* + * Insure that all the components of a pathname exist. + */ +void +pathcheck(char *name) +{ + char *cp; + struct entry *ep; + char *start; + + start = strchr(name, '/'); + if (start == 0) + return; + for (cp = start; *cp != '\0'; cp++) { + if (*cp != '/') + continue; + *cp = '\0'; + ep = lookupname(name); + if (ep == NULL) { + /* Safe; we know the pathname exists in the dump. */ + ep = addentry(name, pathsearch(name)->d_ino, NODE); + newnode(ep); + } + ep->e_flags |= NEW|KEEP; + *cp = '/'; + } +} + +/* + * Change a name to a unique temporary name. + */ +void +mktempname(struct entry *ep) +{ + char oldname[MAXPATHLEN]; + + if (ep->e_flags & TMPNAME) + badentry(ep, "mktempname: called with TMPNAME"); + ep->e_flags |= TMPNAME; + (void) strcpy(oldname, myname(ep)); + freename(ep->e_name); + ep->e_name = savename(gentempname(ep)); + ep->e_namlen = strlen(ep->e_name); + renameit(oldname, myname(ep)); +} + +/* + * Generate a temporary name for an entry. + */ +char * +gentempname(struct entry *ep) +{ + static char name[MAXPATHLEN]; + struct entry *np; + long i = 0; + + for (np = lookupino(ep->e_ino); + np != NULL && np != ep; np = np->e_links) + i++; + if (np == NULL) + badentry(ep, "not on ino list"); + (void) snprintf(name, sizeof(name), "%s%ld%lu", TMPHDR, i, (unsigned long)ep->e_ino); + return (name); +} + +/* + * Rename a file or directory. + */ +void +renameit(char *from, char *to) +{ + if (!Nflag && rename(from, to) < 0) { + warn("cannot rename %s to %s", from, to); + return; + } + Vprintf(stdout, "rename %s to %s\n", from, to); +} + +/* + * Create a new node (directory). + */ +void +newnode(struct entry *np) +{ + char *cp; + if (np->e_type != NODE) + badentry(np, "newnode: not a node"); + cp = myname(np); + if (command == 'C') return; + + if (!Nflag && mkdir(cp, 0777) < 0 && !uflag) { + np->e_flags |= EXISTED; + warn("%s", cp); + return; + } + Vprintf(stdout, "Make node %s\n", cp); +} + +/* + * Remove an old node (directory). + */ +void +removenode(struct entry *ep) +{ + char *cp; + + if (ep->e_type != NODE) + badentry(ep, "removenode: not a node"); + if (ep->e_entries != NULL) + badentry(ep, "removenode: non-empty directory"); + ep->e_flags |= REMOVED; + ep->e_flags &= ~TMPNAME; + cp = myname(ep); + if (!Nflag && rmdir(cp) < 0) { + warn("%s", cp); + return; + } + Vprintf(stdout, "Remove node %s\n", cp); +} + +/* + * Remove a leaf. + */ +void +removeleaf(struct entry *ep) +{ + char *cp; + + if (command == 'C') return; + + if (ep->e_type != LEAF) + badentry(ep, "removeleaf: not a leaf"); + ep->e_flags |= REMOVED; + ep->e_flags &= ~TMPNAME; + cp = myname(ep); + if (!Nflag && unlink(cp) < 0) { + warn("%s", cp); + return; + } + Vprintf(stdout, "Remove leaf %s\n", cp); +} + +/* + * Create a link. + */ +int +linkit(char *existing, char *new, int type) +{ + + /* if we want to unlink first, do it now so *link() won't fail */ + if (uflag && !Nflag) + (void)unlink(new); + + if (type == SYMLINK) { + if (!Nflag && symlink(existing, new) < 0) { + warn("cannot create symbolic link %s->%s", + new, existing); + return (FAIL); + } + } else if (type == HARDLINK) { + int ret; + + if (!Nflag && (ret = link(existing, new)) < 0) { + +#if !defined(__linux__) && !defined(sunos) + struct stat s; + + /* + * Most likely, the schg flag is set. Clear the + * flags and try again. + */ + if (stat(existing, &s) == 0 && s.st_flags != 0 && + chflags(existing, 0) == 0) { + ret = link(existing, new); + chflags(existing, s.st_flags); + } +#else + unsigned long s; + + /* + * Most likely, the immutable or append-only attribute + * is set. Clear the attributes and try again. + */ +#ifdef sunos +#else + if (fgetflags (existing, &s) != -1 && + fsetflags (existing, 0) != -1) { + ret = link(existing, new); + fsetflags(existing, s); + } +#endif +#endif + if (ret < 0) { + warn("warning: cannot create hard link %s->%s", + new, existing); + return (FAIL); + } + } + } else { + panic("linkit: unknown type %d\n", type); + return (FAIL); + } + Vprintf(stdout, "Create %s link %s->%s\n", + type == SYMLINK ? "symbolic" : "hard", new, existing); + return (GOOD); +} + +#if !defined(__linux__) && !defined(sunos) +/* + * Create a whiteout. + */ +int +addwhiteout(char *name) +{ + + if (!Nflag && mknod(name, S_IFWHT, 0) < 0) { + warn("cannot create whiteout %s", name); + return (FAIL); + } + Vprintf(stdout, "Create whiteout %s\n", name); + return (GOOD); +} + +/* + * Delete a whiteout. + */ +void +delwhiteout(struct entry *ep) +{ + char *name; + + if (ep->e_type != LEAF) + badentry(ep, "delwhiteout: not a leaf"); + ep->e_flags |= REMOVED; + ep->e_flags &= ~TMPNAME; + name = myname(ep); + if (!Nflag && undelete(name) < 0) { + warn("cannot delete whiteout %s", name); + return; + } + Vprintf(stdout, "Delete whiteout %s\n", name); +} +#endif + +/* + * find lowest number file (above "start") that needs to be extracted + */ +dump_ino_t +lowerbnd(dump_ino_t start) +{ + struct entry *ep; + + for ( ; start < maxino; start++) { + ep = lookupino(start); + if (ep == NULL || ep->e_type == NODE) + continue; + if (ep->e_flags & (NEW|EXTRACT)) + return (start); + } + return (start); +} + +/* + * find highest number file (below "start") that needs to be extracted + */ +dump_ino_t +upperbnd(dump_ino_t start) +{ + struct entry *ep; + + for ( ; start > ROOTINO; start--) { + ep = lookupino(start); + if (ep == NULL || ep->e_type == NODE) + continue; + if (ep->e_flags & (NEW|EXTRACT)) + return (start); + } + return (start); +} + +/* + * report on a badly formed entry + */ +void +badentry(struct entry *ep, const char *msg) +{ + + fprintf(stderr, "bad entry: %s\n", msg); + fprintf(stderr, "name: %s\n", myname(ep)); + fprintf(stderr, "parent name %s\n", myname(ep->e_parent)); + if (ep->e_sibling != NULL) + fprintf(stderr, "sibling name: %s\n", myname(ep->e_sibling)); + if (ep->e_entries != NULL) + fprintf(stderr, "next entry name: %s\n", myname(ep->e_entries)); + if (ep->e_links != NULL) + fprintf(stderr, "next link name: %s\n", myname(ep->e_links)); + if (ep->e_next != NULL) + fprintf(stderr, + "next hashchain name: %s\n", myname(ep->e_next)); + fprintf(stderr, "entry type: %s\n", + ep->e_type == NODE ? "NODE" : "LEAF"); + fprintf(stderr, "inode number: %lu\n", (unsigned long)ep->e_ino); + panic("flags: %s\n", flagvalues(ep)); +} + +/* + * Construct a string indicating the active flag bits of an entry. + */ +char * +flagvalues(struct entry *ep) +{ + static char flagbuf[BUFSIZ]; + + (void) strcpy(flagbuf, "|NIL"); + flagbuf[0] = '\0'; + if (ep->e_flags & REMOVED) + (void) strcat(flagbuf, "|REMOVED"); + if (ep->e_flags & TMPNAME) + (void) strcat(flagbuf, "|TMPNAME"); + if (ep->e_flags & EXTRACT) + (void) strcat(flagbuf, "|EXTRACT"); + if (ep->e_flags & NEW) + (void) strcat(flagbuf, "|NEW"); + if (ep->e_flags & KEEP) + (void) strcat(flagbuf, "|KEEP"); + if (ep->e_flags & EXISTED) + (void) strcat(flagbuf, "|EXISTED"); + return (&flagbuf[1]); +} + +/* + * Check to see if a name is on a dump tape. + */ +dump_ino_t +dirlookup(const char *name) +{ + struct direct *dp; + dump_ino_t ino; + + ino = ((dp = pathsearch(name)) == NULL) ? 0 : dp->d_ino; + + if (ino == 0 || TSTINO(ino, dumpmap) == 0) + fprintf(stderr, "%s is not on the tape\n", name); + return (ino); +} + +/* + * Elicit a reply. + */ +int +reply(const char *question) +{ + char c; + + do { + fprintf(stderr, "%s? [yn] ", question); + (void) fflush(stderr); + c = getc(terminal); + while (c != '\n' && getc(terminal) != '\n') + if (feof(terminal)) + return (FAIL); + } while (c != 'y' && c != 'n'); + if (c == 'y') + return (GOOD); + return (FAIL); +} + +/* + * handle unexpected inconsistencies + */ +#ifdef __STDC__ +#include +#else +#include +#endif + +void +#ifdef __STDC__ +panic(const char *fmt, ...) +#else +panic(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + + vfprintf(stderr, fmt, ap); + if (yflag) + return; + if (reply("abort") == GOOD) { + if (reply("dump core") == GOOD) + abort(); + exit(1); + } +} + +void resizemaps(dump_ino_t oldmax, dump_ino_t newmax) +{ + char *map; + + if (usedinomap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for active inode map"); + memcpy(map, usedinomap, howmany(oldmax, NBBY)); + free(usedinomap); + usedinomap = map; + } + if (dumpmap) { + map = calloc((unsigned)1, (unsigned)howmany(newmax, NBBY)); + if (map == NULL) + errx(1, "no memory for file dump list"); + memcpy(map, dumpmap, howmany(oldmax, NBBY)); + free(dumpmap); + dumpmap = map; + } +} + +void +GetPathFile(char *source, char *path, char *fname) +{ + char *p, *s; + + *path = 0; + *fname = 0; + p = s = source; + while (*s) { + if (*s == '/') { + p = s + 1; + } + s++; + } + if (p == source) { + *path = 0; + } else { + strncpy(path, source, p - source); + path[p - source] = 0; + } + strcpy(fname, p); +} + +#ifdef USE_QFA +/* + * search for ino in QFA file + * + * if exactmatch: + * if ino found return tape number and tape position + * if ino not found return tnum=0 and tpos=0 + * + * if not exactmatch: + * if ino found return tape number and tape position + * if ino not found return tape number and tape position of last smaller ino + * if no smaller inode found return tnum=0 and tpos=0 + */ +int +Inode2Tapepos(dump_ino_t ino, long *tnum, long long *tpos, int exactmatch) +{ + char *p, *pp; + char numbuff[32]; + unsigned long tmpino; + long tmptnum; + long long tmptpos; + + *tpos = 0; + *tnum = 0; + if (fseek(gTapeposfp, gSeekstart, SEEK_SET) == -1) + return errno; + while (1) { + gSeekstart = ftell(gTapeposfp); /* remember for later use */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) { + return 0; + } + gTps[strlen(gTps) - 1] = 0; /* delete end of line */ + p = gTps; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read inode */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmpino = atol(numbuff); + if (*p == 0) + return 1; /* may NOT happen */ + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapenum */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + if (*p == 0) + return 1; /* may NOT happen */ + tmptnum = atol(numbuff); + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapepos */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmptpos = atoll(numbuff); + + if (exactmatch) { + if (tmpino == ino) { + *tnum = tmptnum; + *tpos = tmptpos; + return 0; + } + } else { + if (tmpino > ino) { + return 0; + } else { + *tnum = tmptnum; + *tpos = tmptpos; + } + } + } + return 0; +} + +#ifdef sunos +int +GetSCSIIDFromPath(char *devPath, long *id) +{ + int len; + char fbuff[2048]; + char path[2048]; + char fname[2048]; + char *fpn = fname; + char idstr[32]; + char *ip = idstr; + + bzero(fbuff, sizeof(fbuff)); + if ((len = readlink(devPath, fbuff, 2048)) == -1) { + return errno; + } + fbuff[len] = 0; + GetPathFile(fbuff, path, fname); + (void)memset(idstr, 0, sizeof(idstr)); + while (*fpn && (*fpn != ',')) { + if (*fpn <= '9' && *fpn >= '0') { + *ip = *fpn; + ip++; + } + fpn++; + } + if (*idstr) { + *id = atol(idstr); + } else { + *id = -1; + } + return 0; +} +#endif +#endif /* USE_QFA */ + +#ifdef DUMP_MACOSX +int +CreateAppleDoubleFileRes(char *oFile, FndrFileInfo *finderinfo, mode_t mode, int flags, + struct timeval *timep, u_int32_t uid, u_int32_t gid) +{ + int err = 0; + int fdout; + char *p; + char *pp; + ASDHeaderPtr hp; + ASDEntryPtr ep; + long thesize; + long n; + + + n = 1; /* number of entries in double file ._ only finderinfo */ + /* + no data fork + n++; + currently no resource fork + n++; + */ + + thesize = sizeof(ASDHeader) + (n * sizeof(ASDEntry)) + INFOLEN; + if ((pp = p = (char *)malloc(thesize)) == NULL) { + err = errno; + return err; + } + + hp = (ASDHeaderPtr)p; + p += sizeof(ASDHeader); + ep = (ASDEntryPtr)p; + p += sizeof(ASDEntry) * n; + + hp->magic = ADOUBLE_MAGIC; + hp->version = ASD_VERSION2; + + bzero(&hp->filler, sizeof(hp->filler)); + hp->entries = (short)n; + + ep->entryID = EntryFinderInfo; + ep->offset = p - pp - CORRECT; + ep->len = INFOLEN; /* sizeof(MacFInfo) + sizeof(FXInfo); */ + bzero(p, ep->len); + bcopy(finderinfo, p, sizeof(FndrFileInfo)); + p += ep->len; + ep++; + + if ((fdout = open(oFile, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { + err = errno; + free(pp); + return err; + } + + /* write the ASDHeader */ + if (write(fdout, pp, sizeof(ASDHeader) - CORRECT) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; + } + /* write the ASDEntries */ + if (write(fdout, pp + sizeof(ASDHeader), thesize - sizeof(ASDHeader)) == -1) { + err = errno; + close(fdout); + free(pp); + unlink(oFile); + return err; + } + + (void)fchown(fdout, uid, gid); + (void)fchmod(fdout, mode); + close(fdout); + (void)fsetflags(oFile, flags); + utimes(oFile, timep); + free(pp); + return err; +} +#endif /* DUMP_MACOSX */ diff --git a/rmt/Makefile.in b/rmt/Makefile.in new file mode 100644 index 0000000..f64f5fa --- /dev/null +++ b/rmt/Makefile.in @@ -0,0 +1,53 @@ +# $Id: Makefile.in,v 1.10 2003/05/08 21:11:39 stelian Exp $ + +top_srcdir= @top_srcdir@ +srcdir= @srcdir@ +top_builddir= .. + +@MCONFIG@ + +ALL_CFLAGS= @CPPFLAGS@ @CFLAGS@ @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) +ALL_LDFLAGS= @LDFLAGS@ @LDOPTS@ @STATIC@ +LIBS= $(GLIBS) +DEPLIBS= ../compat/lib/libcompat.a + +PROG= rmt +SRCS= rmt.c +OBJS= rmt.o +MAN8= rmt.8 + +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +all:: $(PROG) @ERMT@ $(MAN8) + +$(PROG): $(OBJS) $(DEPLIBS) + $(LD) $(ALL_LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +ermt: ermt.o cipher.o $(DEPLIBS) + $(LD) $(ALL_LDFLAGS) -o ermt ermt.o cipher.o $(LIBS) @CRYPTO@ + +ermt.o: rmt.c + $(CC) -c $(ALL_CFLAGS) -DERMT -o ermt.o rmt.c + +$(MAN8): rmt.8.in + sed -e "s|__DATE__|$(DATE)|g" \ + -e "s|__VERSION__|$(VERSION)|g" $< > $@ + +install:: all + $(INSTALL) -d $(SBINDIR) $(MANDIR) + $(INSTALLBIN) $(PROG) $(SBINDIR) + $(INSTALLMAN) $(srcdir)/$(MAN8) $(MANDIR) + +clean:: + rm -f $(PROG) @ERMT@ \#* *.s *.o *.a *~ core rmt.8 + +distclean:: clean + rm -f Makefile Makefile.old .depend + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# + diff --git a/rmt/cipher.c b/rmt/cipher.c new file mode 100644 index 0000000..48da098 --- /dev/null +++ b/rmt/cipher.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Encrypt or decrypt buf, returning a pointer to the transformed data, + * or NULL on error. + * The returned data is the same size as the input data, + * which means we must turn off cipher padding, and require that buflen + * be a multiple of the cipher block size (8 for Blowfish). + * To keep things simple, the return value is a malloc'd + * buffer that is overwritten on each call. + * + * Ken Lalonde , 2003 + */ +char * +cipher(char *buf, int buflen, int do_encrypt) +{ + static EVP_CIPHER_CTX ctx; + static char *out = NULL; /* return value, grown as necessary */ + static int outlen = 0; + static int init = 0, which, blocksize; + int n; + + if (!init) { + static const EVP_CIPHER *cipher; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + // Read key from $HOME/.ermt.key + char *keyfile = ".ermt.key"; + unsigned char buf[128]; + FILE *fp; + int i; + + openlog("ermt", LOG_PID, LOG_DAEMON); + // Not needed: OpenSSL_add_all_algorithms(); + // Not needed: ERR_load_crypto_strings(); + cipher = EVP_bf_cbc(); // or: EVP_aes_{128,192,256}_cbc() + // We want the ability to decrypt the output + // using "openssl enc -d -kfile K -nopad -nosalt", which + // means we must read the key file the same way + // openssl does. But be careful: if the key contains + // \0 or \r or \n, the effective size will be reduced. + if ((fp = fopen(keyfile, "r")) == NULL) { + syslog(LOG_ERR, "Can't open key file %s: %m", keyfile); + return NULL; + } + buf[0] = '\0'; + fgets(buf, sizeof buf, fp); + fclose(fp); + i = strlen(buf); + if ((i > 0) && + ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) + buf[--i]='\0'; + if ((i > 0) && + ((buf[i-1] == '\n') || (buf[i-1] == '\r'))) + buf[--i]='\0'; + if (i < 1) { + syslog(LOG_ERR, "zero length key"); + errno = EINVAL; + return NULL; + } + EVP_BytesToKey(cipher, EVP_md5(), NULL, + buf, strlen(buf), 1, key, iv); + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, do_encrypt); + EVP_CIPHER_CTX_set_padding(&ctx, 0); // -nopad + OPENSSL_cleanse(buf, sizeof buf); + OPENSSL_cleanse(key, sizeof key); + OPENSSL_cleanse(iv, sizeof iv); + blocksize = EVP_CIPHER_CTX_block_size(&ctx); + which = do_encrypt; + init = 1; + } + if (which != do_encrypt) { + syslog(LOG_ERR, "Cannot switch modes"); + errno = EINVAL; + return NULL; + } + if ((buflen % blocksize) != 0) { + syslog(LOG_ERR, "Buffer size is not a multiple of cipher block size"); + errno = EINVAL; + return NULL; + } + if (outlen < buflen+blocksize) { + outlen = (buflen+blocksize) * 2; + out = realloc(out, outlen); + } + if (!EVP_CipherUpdate(&ctx, out, &n, buf, buflen)) { + syslog(LOG_ERR, "EVP_CipherUpdate failed"); + errno = EINVAL; + return NULL; + } + if (n != buflen) { + syslog(LOG_ERR, "EVP_CipherUpdate: %d != %d", n, buflen); + errno = EINVAL; + return NULL; + } + // assert(ctx->buf_len == 0); + return out; +} + +/* Decrypt stdin to stdout, and exit */ +int +decrypt() +{ + char buf[8*1024], *cp; + int n; + + while ((n = fread(buf, 1, sizeof buf, stdin)) > 0) { + if ((cp = cipher(buf, n, 0)) == NULL) { + fprintf(stderr, "ermt: Error decoding input; see daemon.err syslog\n"); + exit(1); + } + fwrite(cp, 1, n, stdout); + } + if (ferror(stdin)) { + perror("ermt: stdin: read"); + exit(1); + } + if (fflush(stdout)) { + perror("ermt: stdout: write"); + exit(1); + } + exit(0); +} diff --git a/rmt/rmt.8.in b/rmt/rmt.8.in new file mode 100644 index 0000000..af41e0a --- /dev/null +++ b/rmt/rmt.8.in @@ -0,0 +1,365 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: rmt.8.in,v 1.10 2003/03/30 15:40:40 stelian Exp $ +.\" +.TH RMT 8 "version __VERSION__ of __DATE__" BSD "System management commands" +.SH NAME +rmt \- remote magtape protocol module +.SH SYNOPSIS +.B rmt +.SH DESCRIPTION +.B Rmt +is a program used by the remote +.BR dump (8), +.BR restore (8) +or +.BR tar (1) +programs in manipulating a magnetic tape drive through an interprocess +communication connection. +.B Rmt +is normally started up with an +.BR rexec (3) +or +.BR rcmd (3) +call. +.PP +The +.B rmt +program accepts requests specific to the manipulation of magnetic tapes, +performs the commands, then responds with a status indication. All responses +are in +.B ASCII +and in one of the following two forms. +.PP +Successful commands have responses of: +.RS +.B A\fInumber\fR\en +.RE +.PP +where +.I number +is an +.B ASCII +representation of a decimal number. +.PP +Unsuccessful commands are responded to with: +.RS +.B E\fIerror-number\fR\en\fIerror-message\fR\en +.RE +.PP +where +.I error-number +is one of the possible error numbers described in +.BR intro (2) +and +.I error-message +is the corresponding error string as printed from a call to +.BR perror (3). +.PP +The protocol is comprised of the following commands, which are sent as +indicated - no spaces are supplied between the command and its arguments, or +between its arguments, and \en indicates that a newline should be supplied: +.TP +.B O\fIdevice\fR\en\fImode\fR\en +Open the specified +.I device +using the indicated +.IR mode . +.I Device +is a full pathname and +.I mode +is an +.B ASCII +representation of a decimal number suitable for passing to +.BR open (2). +If a device had already been opened, it is closed before a new open is +performed. +.TP +.B C\fIdevice\fR\en +Close the currently open device. The +.I device +specified is ignored. +.TP +.B L\fIwhence\fR\en\fIoffset\fR\en +Perform an +.BR lseek (2) +operation using the specified parameters. The response value is that returned +from the +.B lseek +call. +.TP +.B W\fIcount\fR\en +Write data onto the open device. +.B Rmt +reads +.I count +bytes from the connection, aborting if a premature end-of-file is encountered. +The response value is that returned from the +.BR write (2) +call. +.TP +.B R\fIcount\fR\en +Read +.I count +bytes of data from the open device. If +.I count +exceeds the size of the data buffer (10 kilobytes), it is truncated to the +data buffer size. +.B Rmt +then performs the requested +.BR read (2) +and responds with +.B A\fIcount-read\fR\en +if the read was successful; otherwise an error in the standard format is +returned. If the read was successful, the data read is then sent. +.TP +.B I\fIoperation\fR\en\fIcount\fR\en +Perform a +.B MTIOCOP +.BR ioctl (2) +command using the specified parameters. The parameters are interpreted as the +.B ASCII +representations of the decimal values to place in the +.B mt_op +and +.B mt_count +fields of the structure used in the +.B ioctl +call. The return value is the +.I count +parameter when the operation is successful. +.IP +By issuing the +.B I-1\en0\en +command, a client will specify that he is using the VERSION 1 protocol. +.IP +For a VERSION 0 client, the +.I operation +parameter is the platform +.B mt_op +value (could be different if the client and the +.B rmt +server are on two different platforms). For a VERSION 1 client, the +.I operation +parameter is standardized as below: +.RS +.TP +.B 0 +Issue a +.B MTWEOF +command (write +.I count +end-of-file records). +.TP +.B 1 +Issue a +.B MTFSF +command (forward space over +.I count +file marks). +.TP +.B 2 +Issue a +.B MTBSF +command (backward space over +.I count +file marks). +.TP +.B 3 +Issue a +.B MTFSR +command (forward space +.I count +inter-record gaps). +.TP +.B 4 +Issue a +.B MTBSR +command (backward space +.I count +inter-record gaps). +.TP +.B 5 +Issue a +.B MTREW +command (rewind). +.TP +.B 6 +Issue a +.B MTOFFL +command (rewind and put the drive offline). +.TP +.B 7 +Issue a +.B MTNOP +command (no operation, set status only). +.RE +.TP +.B i\fIoperation\fR\en\fIcount\fR\en +Perform an extended +.B MTIOCOP +.BR ioctl (2) +command using the specified parameters. The parameters are interpreted as the +.B ASCII +representations of the decimal values to place in the +.B mt_op +and +.B mt_count +fields of the structure used in the +.B ioctl +call. The return value is the +.I count +parameter when the operation is successful. The possible operations are: +.RS +.TP +.B 0 +Issue a +.B MTCACHE +command (switch cache on). +.TP +.B 1 +Issue a +.B MTNOCACHE +command (switch cache off). +.TP +.B 2 +Issue a +.B MTRETEN +command (retension the tape). +.TP +.B 3 +Issue a +.B MTERASE +command (erase the entire tape). +.TP +.B 4 +Issue a +.B MTEOM +command (position to end of media). +.TP +.B 5 +Issue a +.B MTNBSF +command (backward space count files to BOF). +.RE +.TP +.B S +Return the status of the open device, as obtained with a +.B MTIOCGET +.B ioctl +call. If the operation was successful, an \*(lqack\*(rq is sent with the size +of the status buffer, then the status buffer is sent (in binary, which is +non-portable between different platforms). +.TP +.BI s sub-command +This is a replacement for the previous +.B S +command, portable across different platforms. If the open device is a magnetic +tape, return members of the magnetic tape status structure, as obtained with a +.B MTIOCGET +ioctl call. If the open device is not a magnetic tape, an error is returned. If +the +.B MTIOCGET +operation was successful, the numerical value of the structure member is +returned in decimal. The following sub commands are supported: +.RS +.TP +.B T +return the content of the structure member +.B mt_type +which contains the type of the magnetic tape device. +.TP +.B D +return the content of the structure member +.B mt_dsreg +which contains the "drive status register". +.TP +.B E +return the content of the structure member +.B mt_erreg +which contains the "error register". This structure member must be retrieved +first because it is cleared after each +.B MTIOCGET +ioctl call. +.TP +.B R +return the content of the structure member +.B mt_resid +which contains the residual count of the last I/O. +.TP +.B F +return the content of the structure member +.B mt_fileno +which contains the file number of the current tape position. +.TP +.B B +return the content of the structure member +.B mt_blkno +which contains the block number of the current tape position. +.TP +.B f +return the content of the structure member +.B mt_flags +which contains MTF_ flags from the driver. +.TP +.B b +return the content of the structure member +.B mt_bf +which contains the optimum blocking factor. +.RE +.PP +Any other command causes +.B rmt +to exit. +.SH DIAGNOSTICS +All responses are of the form described above. +.SH SEE ALSO +.BR rcmd (3), +.BR rexec (3), +.I /usr/include/sys/mtio.h, +.BR rdump (8), +.BR rrestore (8) +.SH BUGS +People should be discouraged from using this for a remote file access protocol. +.SH AUTHOR +The +.B dump/restore +backup suit was ported to Linux's Second Extended File System by Remy Card +. He maintained the initial versions of +.B dump +(up and including 0.4b4, released in january 1997). +.PP +Starting with 0.4b5, the new maintainer is Stelian Pop . +.SH AVAILABILITY +The +.B dump/restore +backup suit is available from +.SH HISTORY +The +.B rmt +command appeared in 4.2BSD. diff --git a/rmt/rmt.c b/rmt/rmt.c new file mode 100644 index 0000000..05874a3 --- /dev/null +++ b/rmt/rmt.c @@ -0,0 +1,615 @@ +/* + * Ported to Linux's Second Extended File System as part of the + * dump and restore backup suit + * Remy Card , 1994-1997 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$Id: rmt.c,v 1.28 2003/11/22 16:52:16 stelian Exp $"; +#endif /* not linux */ + +/* + * rmt + */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __linux__ +#include +#endif +#include +#include +#include +#include + +static int tape = -1; + +static char *record; +static int maxrecsize = -1; + +#define SSIZE 64 +static char device[SSIZE]; +static char count[SSIZE], filemode[SSIZE], pos[SSIZE], op[SSIZE]; + +static char resp[BUFSIZ]; + +static FILE *debug; +#define DEBUG(f) if (debug) fprintf(debug, f) +#define DEBUG1(f,a) if (debug) fprintf(debug, f, a) +#define DEBUG2(f,a1,a2) if (debug) fprintf(debug, f, a1, a2) + +/* + * Support for Sun's extended RMT protocol + * code originally written by Jörg Schilling + * and relicensed by his permission from GPL to BSD for use in dump. + * + * rmt_version is 0 for regular clients (Linux included) + * rmt_version is 1 for extended clients (Sun especially). In this case + * we support some extended commands (see below) and we remap + * the ioctl commands to the UNIX "standard", as per: + * ftp://ftp.fokus.gmd.de/pub/unix/star/README.mtio + * + * In order to use rmt version 1, a client must send "I-1\n0\n" + * before issuing the other I commands. + */ +static int rmt_version = 0; +#define RMTI_VERSION -1 +#define RMT_VERSION 1 + +/* Extended 'i' commands */ +#define RMTI_CACHE 0 +#define RMTI_NOCACHE 1 +#define RMTI_RETEN 2 +#define RMTI_ERASE 3 +#define RMTI_EOM 4 +#define RMTI_NBSF 5 + +/* Extended 's' comands */ +#define MTS_TYPE 'T' +#define MTS_DSREG 'D' +#define MTS_ERREG 'E' +#define MTS_RESID 'R' +#define MTS_FILENO 'F' +#define MTS_BLKNO 'B' +#define MTS_FLAGS 'f' +#define MTS_BF 'b' + +static char *checkbuf __P((char *, int)); +static void error __P((int)); +static void getstring __P((char *)); +static unsigned long swaplong __P((unsigned long inv)); +#ifdef ERMT +char *cipher __P((char *, int, int)); +void decrypt __P((void)); +#endif + +int +main(int argc, char *argv[]) +{ + OFF_T rval = 0; + char c; + int n, i, cc, oflags; + unsigned long block = 0; + char *cp; + + int magtape = 0; + +#ifdef ERMT + if (argc > 1 && strcmp(argv[1], "-d") == 0) + decrypt(); /* decrypt stdin to stdout, and exit() */ +#endif + /* Skip "-c /etc/rmt", which appears when rmt is used as a shell */ + if (argc > 2 && strcmp(argv[1], "-c") == 0) + argc -= 2, argv += 2; + argc--, argv++; + if (argc > 0) { + debug = fopen(*argv, "w"); + if (debug == 0) + exit(1); + (void)setbuf(debug, (char *)0); + } +top: + errno = 0; + rval = 0; + if (read(0, &c, 1) != 1) + exit(0); + switch (c) { + + case 'O': + if (tape >= 0) + (void) close(tape); + getstring(device); + getstring(filemode); + DEBUG2("rmtd: O %s %s\n", device, filemode); + /* + * Translate extended GNU syntax into its numeric platform equivalent + */ + oflags = rmtflags_toint(filemode); +#ifdef O_TEXT + /* + * Default to O_BINARY the client may not know that we need it. + */ + if ((oflags & O_TEXT) == 0) + oflags |= O_BINARY; +#endif + DEBUG2("rmtd: O %s %d\n", device, oflags); + /* + * XXX the rmt protocol does not provide a means to + * specify the permission bits; allow rw for everyone, + * as modified by the users umask + */ + tape = OPEN(device, oflags, 0666); + if (tape < 0) + goto ioerror; + block = 0; + { + struct mtget mt_stat; + magtape = ioctl(tape, MTIOCGET, (char *)&mt_stat) == 0; + } + goto respond; + + case 'C': + DEBUG1("rmtd: C (%lu blocks)\n", block); + getstring(device); /* discard */ + if (close(tape) < 0) + goto ioerror; + tape = -1; + block = 0; + goto respond; + +#ifdef USE_QFA +#define LSEEK_GET_TAPEPOS 10 +#define LSEEK_GO2_TAPEPOS 11 +#endif + + case 'L': + getstring(count); + getstring(pos); + DEBUG2("rmtd: L %s %s\n", count, pos); + if (!magtape) { /* traditional */ + switch (atoi(pos)) { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + rval = LSEEK(tape, (OFF_T)atoll(count), atoi(pos)); + break; +#ifdef USE_QFA + case LSEEK_GET_TAPEPOS: + rval = LSEEK(tape, (OFF_T)0, SEEK_CUR); + break; + case LSEEK_GO2_TAPEPOS: + rval = LSEEK(tape, (OFF_T)atoll(count), SEEK_SET); + break; +#endif /* USE_QFA */ + default: + errno = EINVAL; + goto ioerror; + break; + } + } + else { + switch (atoi(pos)) { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + rval = LSEEK(tape, (OFF_T)atoll(count), atoi(pos)); + break; +#ifdef USE_QFA + case LSEEK_GET_TAPEPOS: /* QFA */ + case LSEEK_GO2_TAPEPOS: + { + struct mtop buf; + long mtpos; + + buf.mt_op = MTSETDRVBUFFER; + buf.mt_count = MT_ST_BOOLEANS | MT_ST_SCSI2LOGICAL; + if (ioctl(tape, MTIOCTOP, &buf) < 0) { + goto ioerror; + } + + if (atoi(pos) == LSEEK_GET_TAPEPOS) { /* get tapepos */ + if (ioctl(tape, MTIOCPOS, &mtpos) < 0) { + goto ioerror; + } + rval = (OFF_T)mtpos; + } else { + buf.mt_op = MTSEEK; + buf.mt_count = atoi(count); + if (ioctl(tape, MTIOCTOP, &buf) < 0) { + goto ioerror; + } + rval = (OFF_T)buf.mt_count; + } + } + break; +#endif /* USE_QFA */ + default: + errno = EINVAL; + goto ioerror; + } + } + if (rval < 0) + goto ioerror; + goto respond; + + case 'W': + getstring(count); + n = atoi(count); + if (n < 1) + exit(2); + DEBUG2("rmtd: W %s (block = %lu)\n", count, block); + record = checkbuf(record, n); + for (i = 0; i < n; i += cc) { + cc = read(0, &record[i], n - i); + if (cc <= 0) { + DEBUG("rmtd: premature eof\n"); + exit(2); + } + } +#ifdef ERMT + if ((cp = cipher(record, n, 1)) == NULL) + goto ioerror; +#else + cp = record; +#endif + rval = write(tape, cp, n); + if (rval < 0) + goto ioerror; + block += n >> 10; + goto respond; + + case 'R': + getstring(count); + DEBUG2("rmtd: R %s (block %lu)\n", count, block); + n = atoi(count); + record = checkbuf(record, n); + rval = read(tape, record, n); + if (rval < 0) + goto ioerror; +#ifdef ERMT + if ((cp = cipher(record, rval, 0)) == NULL) + goto ioerror; +#else + cp = record; +#endif + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + (void)write(1, cp, rval); + block += n >> 10; + goto top; + + case 'I': + getstring(op); + getstring(count); + DEBUG2("rmtd: I %s %s\n", op, count); + if (atoi(op) == RMTI_VERSION) { + rval = RMT_VERSION; + rmt_version = 1; + } + else { + struct mtop mtop; + mtop.mt_op = -1; + if (rmt_version) { + /* rmt version 1, assume UNIX/Solaris/Mac OS X client */ + switch (atoi(op)) { +#ifdef MTWEOF + case 0: + mtop.mt_op = MTWEOF; + break; +#endif +#ifdef MTFSF + case 1: + mtop.mt_op = MTFSF; + break; +#endif +#ifdef MTBSF + case 2: + mtop.mt_op = MTBSF; + break; +#endif +#ifdef MTFSR + case 3: + mtop.mt_op = MTFSR; + break; +#endif +#ifdef MTBSR + case 4: + mtop.mt_op = MTBSR; + break; +#endif +#ifdef MTREW + case 5: + mtop.mt_op = MTREW; + break; +#endif +#ifdef MTOFFL + case 6: + mtop.mt_op = MTOFFL; + break; +#endif +#ifdef MTNOP + case 7: + mtop.mt_op = MTNOP; + break; +#endif +#ifdef MTRETEN + case 8: + mtop.mt_op = MTRETEN; + break; +#endif +#ifdef MTERASE + case 9: + mtop.mt_op = MTERASE; + break; +#endif +#ifdef MTEOM + case 10: + mtop.mt_op = MTEOM; + break; +#endif + } + if (mtop.mt_op == -1) { + errno = EINVAL; + goto ioerror; + } + } + else { + /* rmt version 0, assume linux client */ + mtop.mt_op = atoi(op); + } + mtop.mt_count = atoi(count); + if (ioctl(tape, MTIOCTOP, (char *)&mtop) < 0) { + goto ioerror; + } + rval = mtop.mt_count; + } + goto respond; + + case 'i': + { struct mtop mtop; + + getstring (op); + getstring (count); + DEBUG2 ("rmtd: i %s %s\n", op, count); + switch (atoi(op)) { +#ifdef MTCACHE + case RMTI_CACHE: + mtop.mt_op = MTCACHE; + break; +#endif +#ifdef MTNOCACHE + case RMTI_NOCACHE: + mtop.mt_op = MTNOCACHE; + break; +#endif +#ifdef MTRETEN + case RMTI_RETEN: + mtop.mt_op = MTRETEN; + break; +#endif +#ifdef MTERASE + case RMTI_ERASE: + mtop.mt_op = MTERASE; + break; +#endif +#ifdef MTEOM + case RMTI_EOM: + mtop.mt_op = MTEOM; + break; +#endif +#ifdef MTNBSF + case RMTI_NBSF: + mtop.mt_op = MTNBSF; + break; +#endif + default: + errno = EINVAL; + goto ioerror; + } + mtop.mt_count = atoi (count); + if (ioctl (tape, MTIOCTOP, (char *) &mtop) < 0) { + goto ioerror; + } + + rval = mtop.mt_count; + + goto respond; + } + + case 'S': /* status */ + DEBUG("rmtd: S\n"); + { struct mtget mtget; + + if (ioctl(tape, MTIOCGET, (char *)&mtget) < 0) { + goto ioerror; + } + + if (rmt_version) { + rval = sizeof(mtget); + /* assume byte order: + Linux on Intel (little), Solaris on SPARC (big), Mac OS X on PPC (big) + thus need byte swapping from little to big + */ + mtget.mt_type = swaplong(mtget.mt_type); + mtget.mt_resid = swaplong(mtget.mt_resid); + mtget.mt_dsreg = swaplong(mtget.mt_dsreg); + mtget.mt_gstat = swaplong(mtget.mt_gstat); + mtget.mt_erreg = swaplong(mtget.mt_erreg); + mtget.mt_fileno = swaplong(mtget.mt_fileno); + mtget.mt_blkno = swaplong(mtget.mt_blkno); + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + (void)write(1, (char *)&mtget, sizeof (mtget)); + } else { + rval = sizeof (mtget); + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + (void)write(1, (char *)&mtget, sizeof (mtget)); + } + goto top; + } + + case 's': + { char s; + struct mtget mtget; + + DEBUG ("rmtd: s\n"); + + if (read (0, &s, 1) != 1) + goto top; + DEBUG1 ("rmtd: s %d\n", s); + + if (ioctl (tape, MTIOCGET, (char *) &mtget) < 0) { + goto ioerror; + } + + switch (s) { + case MTS_TYPE: + rval = mtget.mt_type; + break; + case MTS_DSREG: + rval = mtget.mt_dsreg; + break; + case MTS_ERREG: + rval = mtget.mt_erreg; + break; + case MTS_RESID: + rval = mtget.mt_resid; + break; + case MTS_FILENO: + rval = mtget.mt_fileno; + break; + case MTS_BLKNO: + rval = mtget.mt_blkno; + break; + case MTS_FLAGS: + rval = mtget.mt_gstat; + break; + case MTS_BF: + rval = 0; + break; + default: + errno = EINVAL; + goto ioerror; + } + + goto respond; + } + + case 'V': /* version */ + getstring(op); + DEBUG1("rmtd: V %s\n", op); + rval = 2; + goto respond; + + default: + DEBUG1("rmtd: garbage command %c\n", c); + exit(3); + } +respond: + DEBUG1("rmtd: A %lld\n", (long long)rval); + (void)sprintf(resp, "A%lld\n", (long long)rval); + (void)write(1, resp, strlen(resp)); + goto top; +ioerror: + error(errno); + goto top; +} + +static void getstring(char *bp) +{ + int i; + char *cp = bp; + + for (i = 0; i < SSIZE - 1; i++) { + if (read(0, cp+i, 1) != 1) + exit(0); + if (cp[i] == '\n') + break; + } + cp[i] = '\0'; +} + +static char * +checkbuf(char *record, int size) +{ + + if (size <= maxrecsize) + return (record); + if (record != 0) + free(record); + record = malloc(size); + if (record == 0) { + DEBUG("rmtd: cannot allocate buffer space\n"); + exit(4); + } + maxrecsize = size; + while (size > 1024 && + setsockopt(0, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0) + size -= 1024; + return (record); +} + +static void +error(int num) +{ + + DEBUG2("rmtd: E %d (%s)\n", num, strerror(num)); + (void)snprintf(resp, sizeof(resp), "E%d\n%s\n", num, strerror(num)); + (void)write(1, resp, strlen(resp)); +} + +static unsigned long +swaplong(unsigned long inv) +{ + union lconv { + unsigned long ul; + unsigned char uc[4]; + } *inp, outv; + + inp = (union lconv *)&inv; + + outv.uc[0] = inp->uc[3]; + outv.uc[1] = inp->uc[2]; + outv.uc[2] = inp->uc[1]; + outv.uc[3] = inp->uc[0]; + + return (outv.ul); +}