From 5a08594ac8848d30e421342415139fd1c54e65bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wanderlei=20H=C3=BCttel?= Date: Thu, 11 Aug 2016 08:12:38 -0300 Subject: [PATCH] Import project from sourceforge.net --- AUTHORS | 9 + COPYING | 381 ++ ChangeLog | 75 + INSTALL | 52 + Makefile.am | 13 + Makefile.in | 817 +++ NEWS | 1 + README | 6 + ReleaseNotes | 254 + aclocal.m4 | 1039 ++++ config.guess | 1558 ++++++ config.h.in | 310 ++ configure | 7629 +++++++++++++++++++++++++++++ configure.ac | 71 + depcomp | 791 +++ doc/Makefile.am | 2 + doc/Makefile.in | 509 ++ doc/example-vchanger-udev.rules | 5 + doc/vchanger-example.conf | 75 + doc/vchanger.8 | 206 + doc/vchanger.8.asciidoc | 180 + doc/vchanger.conf.5 | 145 + doc/vchanger.conf.5.asciidoc | 120 + doc/vchangerHowto.html | 1845 +++++++ install-sh | 527 ++ missing | 215 + rpm/vchanger.el6.spec | 91 + rpm/vchanger.el7.spec | 91 + scripts/Makefile.am | 4 + scripts/Makefile.in | 498 ++ scripts/vchanger-genudevrules | 28 + scripts/vchanger-launch-mount.sh | 12 + scripts/vchanger-launch-umount.sh | 12 + scripts/vchanger-mount-uuid.sh | 93 + scripts/vchanger-umount-uuid.sh | 76 + scripts/vchanger.default | 2 + src/Makefile.am | 14 + src/Makefile.in | 722 +++ src/bconsole.cpp | 176 + src/bconsole.h | 29 + src/changerstate.cpp | 851 ++++ src/changerstate.h | 137 + src/compat/getline.c | 81 + src/compat/getline.h | 38 + src/compat/gettimeofday.c | 118 + src/compat/gettimeofday.h | 62 + src/compat/getuid.c | 46 + src/compat/getuid.h | 45 + src/compat/localtime_r.c | 57 + src/compat/localtime_r.h | 39 + src/compat/readlink.c | 126 + src/compat/readlink.h | 42 + src/compat/sleep.c | 39 + src/compat/sleep.h | 42 + src/compat/symlink.c | 87 + src/compat/symlink.h | 42 + src/compat/syslog.c | 57 + src/compat/syslog.h | 80 + src/compat_defs.h | 37 + src/diskchanger.cpp | 993 ++++ src/diskchanger.h | 80 + src/errhandler.cpp | 73 + src/errhandler.h | 43 + src/inifile.cpp | 1185 +++++ src/inifile.h | 190 + src/loghandler.cpp | 206 + src/loghandler.h | 70 + src/mypopen.cpp | 726 +++ src/mypopen.h | 37 + src/targetver.h | 24 + src/tstring.cpp | 476 ++ src/tstring.h | 80 + src/util.cpp | 192 + src/util.h | 33 + src/uuidlookup.c | 364 ++ src/uuidlookup.h | 37 + src/vchanger.cpp | 661 +++ src/vconf.cpp | 309 ++ src/vconf.h | 70 + src/win32_util.c | 259 + src/win32_util.h | 50 + win32/installer.nsi | 150 + win32build | 52 + 83 files changed, 27069 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 ReleaseNotes create mode 100644 aclocal.m4 create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100755 depcomp create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/example-vchanger-udev.rules create mode 100644 doc/vchanger-example.conf create mode 100644 doc/vchanger.8 create mode 100644 doc/vchanger.8.asciidoc create mode 100644 doc/vchanger.conf.5 create mode 100644 doc/vchanger.conf.5.asciidoc create mode 100644 doc/vchangerHowto.html create mode 100755 install-sh create mode 100755 missing create mode 100644 rpm/vchanger.el6.spec create mode 100644 rpm/vchanger.el7.spec create mode 100644 scripts/Makefile.am create mode 100644 scripts/Makefile.in create mode 100644 scripts/vchanger-genudevrules create mode 100644 scripts/vchanger-launch-mount.sh create mode 100644 scripts/vchanger-launch-umount.sh create mode 100644 scripts/vchanger-mount-uuid.sh create mode 100644 scripts/vchanger-umount-uuid.sh create mode 100644 scripts/vchanger.default create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/bconsole.cpp create mode 100644 src/bconsole.h create mode 100644 src/changerstate.cpp create mode 100644 src/changerstate.h create mode 100644 src/compat/getline.c create mode 100644 src/compat/getline.h create mode 100644 src/compat/gettimeofday.c create mode 100644 src/compat/gettimeofday.h create mode 100644 src/compat/getuid.c create mode 100644 src/compat/getuid.h create mode 100644 src/compat/localtime_r.c create mode 100644 src/compat/localtime_r.h create mode 100644 src/compat/readlink.c create mode 100644 src/compat/readlink.h create mode 100644 src/compat/sleep.c create mode 100644 src/compat/sleep.h create mode 100644 src/compat/symlink.c create mode 100644 src/compat/symlink.h create mode 100644 src/compat/syslog.c create mode 100644 src/compat/syslog.h create mode 100644 src/compat_defs.h create mode 100644 src/diskchanger.cpp create mode 100644 src/diskchanger.h create mode 100644 src/errhandler.cpp create mode 100644 src/errhandler.h create mode 100644 src/inifile.cpp create mode 100644 src/inifile.h create mode 100644 src/loghandler.cpp create mode 100644 src/loghandler.h create mode 100644 src/mypopen.cpp create mode 100644 src/mypopen.h create mode 100644 src/targetver.h create mode 100644 src/tstring.cpp create mode 100644 src/tstring.h create mode 100644 src/util.cpp create mode 100644 src/util.h create mode 100644 src/uuidlookup.c create mode 100644 src/uuidlookup.h create mode 100644 src/vchanger.cpp create mode 100644 src/vconf.cpp create mode 100644 src/vconf.h create mode 100644 src/win32_util.c create mode 100644 src/win32_util.h create mode 100644 win32/installer.nsi create mode 100755 win32build diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..fd51a0c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,9 @@ +This file contains a list of the people who have contributed code and/or +documentation to the vchanger project. Thanks to all! + + +Principle Authors: + + Josh Fisher + +Contributors: diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..cb1251f --- /dev/null +++ b/COPYING @@ -0,0 +1,381 @@ +COPYRIGHTS: +Vchanger is Copyright (C) 2008-2015 Josh Fisher. + +LICENSE: +Vchanger is licensed under the GNU GPL version 2, the full text +of which is included below. + +IP RIGHTS: +Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe +the patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient +for claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each +Recipient hereby assumes sole responsibility to secure any other +intellectual property rights needed, if any. For example, if a +third party patent license is required to allow Recipient to +distribute the Program, it is Recipient's responsibility to +acquire that license before distributing the Program. + + +DISCLAIMER: +NO WARRANTY +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER +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. + +===================================== + + +============== Text of GPL version 2 license ======== + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..6111246 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,75 @@ +vchanger ChangeLog + +1.0.1 (2015-06-09) + - When looking up the mountpoint of a magazine by UUID with libudev, + also look for mountpoint of device alias names in DEVLINKS in addition + to the DEVNAME. (Fixes bug 12) + - The f_mntonname field in struct statfs was misspelled, causing a compile + error on BSD systems. (Fixes bug 10) + - Use static linking of libwinpthread on Windows builds to prevent missing + libwinpthreads-1.dll error. (Fixes bug 11) + - Set signal handler for SIGPIPE to SIG_IGN and do not reacquire process + lockfile when deleting the update lockfile. This should prevent a race + condition in vchanger when Bacula invokes other instances of vchanger + recursively when an 'update slots' or 'label barcodes' command is issued + via bconsole. (Fixes bug 9) + - Fixed nsis script error causing Windows installer to install incorrectly + for 64-bit Windows and fail to create Start Menu items. Also now correctly + removes itself from the Installed Programs list when uninstalled. +1.0.0 (2015-04-14) + - Major change to magazine and work directory structure. + - Virtual drive symlink points to volume file directly + - All drive and magazine state info kept in work directory + - Magazines have a dynamic number of virtual slots corresponding + to a variable number of volume files + - Volume files may be moved from one magazine to another + - Allow an unlimited number of virtual drives + - Add ability to issue 'update slots' and 'label barcodes' commands + to Bacula to support plug-n-play of removable drives + - Add support for undocumented Bacula Autochanger Interface command LISTALL + - Added extended API command CREATEVOLS to allow creating and labelling + volume files with a single command. + - Added extended API command REFRESH to support plug-n-play of removable + drives + - Removed deprecated extended API command INITMAG + - Add udev support for finding devices by UUID + - Increased amount of logging + - Enable use of getfsstat() for finding mountpoint by UUID to support + building for BSD / OSX + - Allow building without UUID capability to support minimal systems having + neither libudev nor libblkid/libuuid. + - Changed Windows version requirement to Server 2008+ / Vista+ + - Allow cross-compile of 64-bit Windows target +0.8.6 (2010-05-13) + - Use opendir instead of stat to trigger automounts + - Add ability to configure logging level + - Add extensive logging output to enhance debugging + - Maintain persistent magazine bay state to prevent magazines + in multi-magazine changers from inadvertently being moved + when a lower numbered bay has its magazine detached. +0.8.5 (2010-02-05) + - Fix esfsprogs link errors on some Linux distros (bug 2941290) + - Merge "safe strncat" patch +0.8.4 (2009-12-02) + - Ignore slot number passed to 'loaded' command (bug 2907225) + - Fix libblkid linking for FreeBSD (bug 2872006) +0.8.3 (2009-10-27) + - Add specification of magazines by partition UUID + - Add LISTMAGS command to list magazines assigned to an autochanger + - Empty, rather than delete, loadedN files to prevent out of space + error on magazine partition + - Fix error parsing index files. (bug 2785183) + - Fixes for FreeBSD compatibility. (bug 2872006) +0.8.2 [2009-04-14] + - Corrections to documentation +0.8.1 [2009-01-27] + - Add extended command INITMAG for initializing new magazines + - Added command line flags to set uid and gid when run as root + - Force LOADED command to return zero when no slot is loaded + - Changed 99-by-label-fix.rules to work with centos5/el5 + - Added stateN files to track the loaded state of each virtual + drive when last invoked + - Removed debug line inadvertently left in by_label_fix.sh + +0.8.0 [2008-10-03] + - Initial Release diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f2ffcfc --- /dev/null +++ b/INSTALL @@ -0,0 +1,52 @@ + +This file explains general installation instructions. The documentation +included in the ./doc directory of the vchanger source archive should be +consulted instead. + + +-------------------------------------------------------------------------- +Using GNU autoconfig +-------------------------------------------------------------------------- + 1. Run ./configure to generate config.h and the various Makefiles. + ./configure --help gives a list of possible options. Usually, + the default options will suffice to install vchanger under the + /usr/local directory. + + Some systems require unusual options for compilation or linking that + the `configure' script does not know about. You can give `configure' + initial values for variables by setting them in the environment. Using + a Bourne-compatible shell, you can do that on the command line like + this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + Or if you're using a non Bourne-compatible shell, you can do: + sh -c 'CFLAGS="-O2 -g" ./configure + + A typical vchanger development configuration for Linux is: + + CFLAGS="-g -O2 -Wall" \ + ./configure + + 2. Carefully review the output from ./configure. If it is not + what you want, re-run the ./configure. Often ./configure "caches" + things and thus remembers the last ./configure options. If you + want to be sure you are starting fresh after a ./configure, + do a: + + make distclean + + before re-running ./configure. "make distclean" wipes out any + knowledge of the ./configure, so don't do it after you have a + configuration that suits your needs, otherwise the "make" will + not work. + + 3. Build it + make + + 4. Install it + make install-strip + + 5. Create a autochanger configuration file and configure Bacula(TM) + to use that autochanger. Please see the documentation in the + ./doc directory for details. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..8949d4d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src doc scripts +docdir = $(datadir)/doc/$(PACKAGE)-${VERSION} +doc_DATA = AUTHORS \ + ChangeLog \ + COPYING \ + INSTALL \ + NEWS \ + README \ + ReleaseNotes \ + doc/vchangerHowto.html \ + doc/vchanger-example.conf \ + doc/example-vchanger-udev.rules diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..8351f19 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,817 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = . +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/configure $(am__configure_deps) \ + $(srcdir)/config.h.in AUTHORS COPYING ChangeLog INSTALL NEWS \ + README config.guess depcomp install-sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(docdir)" +DATA = $(doc_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope distdir dist dist-all distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINLDADD = @WINLDADD@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = $(datadir)/doc/$(PACKAGE)-${VERSION} +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src doc scripts +doc_DATA = AUTHORS \ + ChangeLog \ + COPYING \ + INSTALL \ + NEWS \ + README \ + ReleaseNotes \ + doc/vchangerHowto.html \ + doc/vchanger-example.conf \ + doc/example-vchanger-udev.rules + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-docDATA: $(doc_DATA) + @$(NORMAL_INSTALL) + @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ + done + +uninstall-docDATA: + @$(NORMAL_UNINSTALL) + @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(docdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-docDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-docDATA + +.MAKE: $(am__recursive_targets) all install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-am clean clean-cscope clean-generic \ + cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ + dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-docDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + tags-am uninstall uninstall-am uninstall-docDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..a91d1f0 --- /dev/null +++ b/NEWS @@ -0,0 +1 @@ +Please see the ReleaseNotes file. diff --git a/README b/README new file mode 100644 index 0000000..23c48a0 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +vchanger is designed to implement a disk-based virtual autochanger device for +use with Bacula(TM), an open-source network backup solution. + +Please see the vchangerHowto.html in the doc directory of the vchanger source +for further documentation and installation instructions. + diff --git a/ReleaseNotes b/ReleaseNotes new file mode 100644 index 0000000..c9678c3 --- /dev/null +++ b/ReleaseNotes @@ -0,0 +1,254 @@ + Release Notes for vchanger 1.0.1 2015-06-09 + + Release 1.0.1 + + This is a bug fix release, fixing four issues found in version 1.0.0. + Additionally, the Windows installer was fixed to correctly install on + 64-bit Windows and create Start Menu items. + +Bugs Fixed: + + 9 Vchanger may hang when issuing commands to Bacula + 10 uuidlookup.c compilation failure on FreeBSD 9.3 + 11 Missing libwinpthread-1.dll error in Windows version + 12 Mounted magazines specified by UUID not always detected + + ================================================================== + + + Release 1.0.0 + + This is a major release adding several features and a change in the + structure of magazines and the way volume files are "loaded" into + virtual drives. These changes allow for an unlimited and variable + number of volume files on each magazine, and allow adding and deleting + volumes to/from magazines, as well as moving volume files from one + magazine to another. Virtual drives are now symlinks dynamically + created by the LOAD command. An unlimited number of virtual drives per + autochanger is supported without requiring a vchanger configuration + change. The number of virtual drives used is determined solely by the + Device resources defined in bacula-sd.conf. + + Also, vchanger will now automatically issue 'update slots' and + 'label barcodes' commands to Bacula via bconsole when it detects a + change in the availability of any of its defined magazines or when + volume files are created with the CREATEVOLS command. Together with + an automounting mechanism, this makes the attachment and detachment + of removable drives a plug-n-play operation. + + To aid in using removable drives on systems having udev, vchanger now + includes a udev rules generator and helper scripts to enable the + automatic mounting of magazine filesystems triggered by udev hotplug + events. The advantage to using this automounting method, as opposed to + autofs or window manager automounters using dbus, etc., is that these + scripts will invoke vchanger with a new REFRESH command that will issue + an 'update slots' command via bconsole whenever removable drives + are attached or detached. + + Change Summary: + + The concept of a 'magazine' has changed. A magazine remains a + directory, usually the mountpoint of a filesystem, however no metadata + files are now stored on the magazines and volume files are not renamed + when loading and unloading virtual drives. There is now no requirement + that all magazines have the same number of volumes, and volume files + may have any filename. New volume files can be created on a magazine + at any time. A new extended interface command, CREATEVOLS, has been + implemented for this purpose. A magazine is now simply a filesystem + (or directory) containing some variable number of volume files. Any + directory containing volume files can be used as a magazine in + vchanger, including for example volumes created using Bacula's + built-in disk storage handling. Volume files may be deleted from + magazines or moved between magazines. The only caveat is that the + volume's Media Type must match that of the autochanger's Storage + resource. + + Virtual drives are now simply a symlink in the autochanger's work + directory. The drive number is the name of the symlink. For example, + if the autochanger's work directory is /var/spool/vchanger/changer1, + then virtual drive 0 is a symlink at the path + /var/spool/vchanger/changer1/0. The symlink's path is then specified as + the Archive Device in the Device resource defined in bacula-sd.conf for + the autochanger's drive 0. Vchanger implements the LOAD command by + creating this symlink pointing at the volume file mapped to the slot + requested to be loaded. A subsequent UNLOAD command deletes the + symlink. In previous versions, a LOAD created a symlink pointing to the + mountpoint of the magazine and then renamed the volume file on the + magazine to 'drive0', 'drive1', etc. This was because the original + design criteria, (dating to before the release of Bacula 2.0.0), + required that vchanger run on Windows Server 2003, which did not have + the capability of file-level symlinks. However, file-level symlinks is + a much more robust method, handling any "out of space" conditions in a + clean, expected way. For that reason, use of vchanger on versions of + Windows without file-level symlinks is no longer supported. + + An autochanger's magazines are assigned in its vchanger configuration + file. An unlimited number of magazines is supported and the storage space used + by an autochanger can be scaled at any time by simply adding additional + magazines and creating volume files on them. Expansion of the storage + space does not require any change to Bacula's configuration. Any + combination of one or more of the assigned magazines can be attached + (mounted) at any time. + + When a magazine is attached or detached there is of course a change in + which volumes are available for reading and writing. Bacula must be + instructed to update its database to reflect the change. This is + analogous to swapping tapes in a tape autochanger library. Bacula has a + bconsole command used for this purpose, the 'update slots' command. In + general, one would insert or remove tapes and then issue an 'update slots' + command in bconsole to inform Bacula of the change. With vchanger, + attaching or detaching a magazine also requires that the 'update slots' + command be issued, however vchanger now detects changes to the currently + available volume files and automatically issues the 'update slots' + command when needed. This allows swapping magazines to be a true + plug-n-play operation. + + The scripts directory in the vchanger source tree contains a script to + generate the udev rules needed to automatically mount the magazines + filesystems defined in the vchanger configuration file. These rules will + cause udev to launch scripts, also included in the scripts directory, to + handle a "hot add" event by mounting the magazine filesystem and invoking + vchanger with the REFRESH command to issue an 'update slots' command to + Bacula. Likewise, a "hot delete" event will launch a script to unmount + the filesystem and again invoke vchanger with the REFRESH command. + + If vchanger is compiled on a system supporting udev, then libudev will be + used to determine the device node of magazine partitions specified by + UUID. If compiled on a system without udev, the older method of using + libblkid and libuuid will be used if available. For Windows builds, + win32 API functions are used to map filesystem UUID to device node. If + the getmntent() function is not available on the target system for + determining a filesystem's mountpoint, then vchanger will use the + getfsstat() function, allowing magazines to be specified by UUID on many + BSD and OSX systems. A build for a minimal system having neither libudev + nor libblkid will succeed, however specifying magazines by UUID will not + function and result in an error, meaning that such minimal systems must + only specify magazines by directory path. These changes should alleviate + many of the problems people have had in the past building vchanger for + non-Linux systems. + + Bugs Fixed: + 5 Compile errors on Debian or Ubuntu + 6 Broken libblkid returns wrong device for UUID + 7 Limitation on number of virtual drives + 8 Compile errors under Solaris 10 + + ================================================================== + + + Release 0.8.6 + + When using the automount_dir directive, opendir() is now used rather + than stat(), to trigger automounts. For some combinations of Linux + kernel and older versions of autofs, stat() is not sufficient to + trigger an automount. + + Extensive logging was added to this version, along with a new + configuration directive to set the logging level. This should greatly + help problem diagnosis. + + State information for the magazine bays is now kept in the work + directory along with virtual drive state. In a multi-magazine changer, + when a magazine was unloaded from a bay, magazines in higher numbered + bays were being shifted down to appear loaded into a different bay + than they were before the magazine was unloaded. With this version, + magazines will remain loaded in the same bay until they are unloaded. + + Bugs Fixed: + + ================================================================== + + + Release 0.8.5 + + Minor bug fix release. Fixes link errors for older versions of + e2fsprogs on some distros (bug 4). Also applies the "safe strncat" + patch to prevent a buffer overrun present in strncat in some standard + C libraries. + + Bugs Fixed: + 4 Compile errors related to e2fsprogs libraries + + ================================================================== + + + Release 0.8.4 + + This release is a bug fix release. All users of version 0.8.3 should + upgrade to 0.8.4 to prevent a bug causing Bacula to mark volumes in + error. + + Change Summary: + The slot number passed in parameter 3 is now ignored for the LOADED + command. This should fix a bug causing Bacula to mark a volume + loaded into a drive in error when a job starts after the magazine + has been removed. + + Bugs Fixed: + 3 LOADED command fails when param 3 (slot) is zero + 2 Compile fail on FreeBSD 7.2 + + ================================================================== + + Release 0.8.3 + + This release adds the ability to specify magazine partitions by UUID, + making it much easier to use multiple simultaneous magazines. + + Change Summary: + + Specifying magazine partitions by UUID is a paradigm shift in the way + magazines may be assigned to a particular autochanger. Previously, + magazines were assigned to an autochanger by giving the magazine a + filesystem label matching the autochanger's name. Standard udev + rules on many distributions create a device symlink in + /dev/disk/by-label that allow easily configuring autofs to mount the + magazine at a known mountpoint. This works well for a single magazine + autochanger, but for a multi-magazine autochanger special udev rules + are needed to create unique device symlinks when all of the + magazines have the same filesystem label. Since the standard udev + rules on most systems create device symlinks by filesystem UUID + under /dev/disk/by-uuid, assigning magazines to an autochanger by UUID + makes it much easier to configure automounting that will work for an + autochanger with any number of simultaneously mounted magazines. + + Note that magazines may still be specified as a directory path, so the + previous methods still work, however it is recommended to assign + magazines by UUID if possible. + + As an aid to working with multi-magazine autochangers, a new extended + API command, LISTMAGS, was added to list the magazines currently + "inserted" into each of the autochanger's magazine bays. Like the + INITMAG command, it is an extension to the Bacula Autochanger API and so + is never invoked by Bacula. + + Bugs Fixed: + 1 Unable to detect when drives inserted using the vchanger + 2 Compile fail on FreeBSD 7.2 + + ================================================================== + + Release 0.8.2 + + This release fixes some documentation errors. No changes were + made to the vchanger source. + + Change Summary: + 2009-04-14 + - Fixed ambiguities in the Howto kindly pointed out by Sean Brannon. + 2009-01-27 + - Added command line flags to set uid and gid when run as root + - Force LOADED command to return zero when no slot is loaded + - Changed 99-by-label-fix.rules to work with centos5/el5 + - Added stateN files to track the loaded state of each virtual + drive when last invoked + - Removed debug line inadvertently left in by_label_fix.sh + + 2008-10-03 + - This initial release has been running on a test server with + Bacula 2.4.2 on Linux for over a week, so is considered beta. + + Bugs Fixed: + + ================================================================= + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..f6192c7 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1039 @@ +# generated automatically by aclocal 1.13.4 -*- Autoconf -*- + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.13' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.13.4], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.13.4])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2013 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..b79252d --- /dev/null +++ b/config.guess @@ -0,0 +1,1558 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2013 Free Software Foundation, Inc. + +timestamp='2013-06-10' + +# 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 3 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, see . +# +# 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. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches with a ChangeLog entry to config-patches@gnu.org. + + +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 1992-2013 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 ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # 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. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + 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 ; set_cc_for_build= ;' + +# 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 + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + ;; +esac + +# 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 tuples: *-*-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 ;; + sh5el) machine=sh5le-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 -q __ELF__ + 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 + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # 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 ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # 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. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + 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 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + 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 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + 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 ;; + 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 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + 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 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # 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 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + 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 -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + 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 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????: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 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + 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 ;; + *: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 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + 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 ;; + *:AIX:*:[4567]) + 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 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 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 -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 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 -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + 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 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + 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 ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + 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 i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + 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 -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + or1k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + 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-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + 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 ;; + 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 ;; + 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 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + 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 ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + 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 ;; + 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 ;; + 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 i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + 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 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*: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 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*: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; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + 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; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *: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 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + 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 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *: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 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *: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 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +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\n"); 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 -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# 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 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + 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..f650f97 --- /dev/null +++ b/config.h.in @@ -0,0 +1,310 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Copyright notice */ +#undef COPYRIGHT_NOTICE + +/* Define to 1 if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Have blkid_evaluate_tag function */ +#undef HAVE_BLKID_EVALUATE_TAG + +/* Have blkid_get_devname function */ +#undef HAVE_BLKID_GET_DEVNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getfsstat' function. */ +#undef HAVE_GETFSSTAT + +/* Define to 1 if you have the `getline' function. */ +#undef HAVE_GETLINE + +/* Define to 1 if you have the `getmntent' function. */ +#undef HAVE_GETMNTENT + +/* Define to 1 if you have the `getmntent_r' function. */ +#undef HAVE_GETMNTENT_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if you have the header file. */ +#undef HAVE_GRP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBGEN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBUDEV_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MNTENT_H + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPTARG_H + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define to 1 if you have the `readlink' function. */ +#undef HAVE_READLINK + +/* Define to 1 if you have the `setlocale' function. */ +#undef HAVE_SETLOCALE + +/* have header shlobj.h */ +#undef HAVE_SHLOBJ_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_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 `symlink' function. */ +#undef HAVE_SYMLINK + +/* Define to 1 if you have the `syslog' function. */ +#undef HAVE_SYSLOG + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BITYPES_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_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_TIMESPEC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_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_SYS_UCRED_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if typeof works with your compiler. */ +#undef HAVE_TYPEOF + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_VARARGS_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* have header windows.h */ +#undef HAVE_WINDOWS_H + +/* have header winioctl.h */ +#undef HAVE_WINIOCTL_H + +/* have header winreg.h */ +#undef HAVE_WINREG_H + +/* have header winsock.h */ +#undef HAVE_WINSOCK_H + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Name of package */ +#undef PACKAGE + +/* 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 home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef int32_t + +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to __typeof__ if your compiler spells it that way. */ +#undef typeof + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t diff --git a/configure b/configure new file mode 100755 index 0000000..c12d3e8 --- /dev/null +++ b/configure @@ -0,0 +1,7629 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for vchanger 1.0.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 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 more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and jfisher@jaybus.com +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # 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 sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='vchanger' +PACKAGE_TARNAME='vchanger' +PACKAGE_VERSION='1.0.1' +PACKAGE_STRING='vchanger 1.0.1' +PACKAGE_BUGREPORT='jfisher@jaybus.com' +PACKAGE_URL='' + +ac_unique_file="src" +ac_config_libobj_dir=src/compat +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_header_list= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +WINLDADD +EGREP +GREP +CPP +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_dependency_tracking +enable_largefile +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# 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. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +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 + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -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) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$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 ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$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 ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + 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 ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$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_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=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 ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_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'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +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 + 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 + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# 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 the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + 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 + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# 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 vchanger 1.0.1 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 \`..'] + +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] + --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] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/vchanger] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of vchanger 1.0.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-largefile omit support for large files + +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 + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + 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. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested 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 + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +vchanger configure 1.0.1 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 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 +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_find_intX_t LINENO BITS VAR +# ----------------------------------- +# Finds a signed integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_intX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 +$as_echo_n "checking for int$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) + < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_intX_t + +# ac_fn_c_find_uintX_t LINENO BITS VAR +# ------------------------------------ +# Finds an unsigned integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_uintX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 +$as_echo_n "checking for uint$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_uintX_t + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## --------------------------------- ## +## Report this to jfisher@jaybus.com ## +## --------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* 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_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by vchanger $as_me 1.0.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +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` +/usr/bin/hostinfo = `(/usr/bin/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=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&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_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=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append 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 + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset 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: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > 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 + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + 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. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +as_fn_append ac_header_list " stdio.h" +as_fn_append ac_header_list " stdlib.h" +as_fn_append ac_header_list " string.h" +as_fn_append ac_header_list " stdarg.h" +as_fn_append ac_header_list " stddef.h" +as_fn_append ac_header_list " time.h" +as_fn_append ac_header_list " sys/time.h" +as_fn_append ac_header_list " sys/timespec.h" +as_fn_append ac_header_list " sys/wait.h" +as_fn_append ac_header_list " limits.h" +as_fn_append ac_header_list " locale.h" +as_fn_append ac_header_list " syslog.h" +as_fn_append ac_header_list " sys/types.h" +as_fn_append ac_header_list " strings.h" +as_fn_append ac_header_list " alloca.h" +as_fn_append ac_header_list " sys/bitypes.h" +as_fn_append ac_header_list " getopt.h" +as_fn_append ac_header_list " utime.h" +as_fn_append ac_header_list " sys/stat.h" +as_fn_append ac_header_list " inttypes.h" +as_fn_append ac_header_list " ctype.h" +as_fn_append ac_header_list " errno.h" +as_fn_append ac_header_list " unistd.h" +as_fn_append ac_header_list " varargs.h" +as_fn_append ac_header_list " mntent.h" +as_fn_append ac_header_list " sys/param.h" +as_fn_append ac_header_list " sys/mount.h" +as_fn_append ac_header_list " sys/ucred.h" +as_fn_append ac_header_list " grp.h" +as_fn_append ac_header_list " pwd.h" +as_fn_append ac_header_list " dirent.h" +as_fn_append ac_header_list " fcntl.h" +as_fn_append ac_header_list " sys/select.h" +as_fn_append ac_header_list " optarg.h" +as_fn_append ac_header_list " pthread.h" +as_fn_append ac_header_list " libgen.h" +as_fn_append ac_header_list " io.h" +as_fn_append ac_header_list " signal.h" +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; 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,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_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 + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_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. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +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 + + + +$as_echo "#define COPYRIGHT_NOTICE \"vchanger Copyright (c) 2006-2015 Josh Fisher\"" >>confdefs.h + + + +ac_config_headers="$ac_config_headers config.h" + +am__api_version='1.13' + +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 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# 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. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&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_fn_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 + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +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. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$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' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='vchanger' + VERSION='1.0.1' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + + +# Checks for programs. +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_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" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +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 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM 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. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; 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 | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* 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 -std 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 -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 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 +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +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 +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +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 + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +# Checks for typedefs, structures, and compiler characteristics. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for typeof syntax and keyword spelling" >&5 +$as_echo_n "checking for typeof syntax and keyword spelling... " >&6; } +if ${ac_cv_c_typeof+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_typeof=no + for ac_kw in typeof __typeof__ no; do + test $ac_kw = no && break + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int value; + typedef struct { + char a [1 + + ! (($ac_kw (value)) + (($ac_kw (value)) 0 < ($ac_kw (value)) -1 + ? ($ac_kw (value)) - 1 + : ~ (~ ($ac_kw (value)) 0 + << sizeof ($ac_kw (value)))))]; } + ac__typeof_type_; + return + (! ((void) ((ac__typeof_type_ *) 0), 0)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_typeof=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test $ac_cv_c_typeof != no && break + done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_typeof" >&5 +$as_echo "$ac_cv_c_typeof" >&6; } + if test $ac_cv_c_typeof != no; then + +$as_echo "#define HAVE_TYPEOF 1" >>confdefs.h + + if test $ac_cv_c_typeof != typeof; then + +cat >>confdefs.h <<_ACEOF +#define typeof $ac_cv_c_typeof +_ACEOF + + fi + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#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)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +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=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } +if ${ac_cv_header_stdbool_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(_Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + _Bool q = true; + _Bool *pq = &q; + +int +main () +{ + + bool e = &s; + *pq |= q; + *pq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdbool_h=yes +else + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +$as_echo "$ac_cv_header_stdbool_h" >&6; } + ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + + +if test $ac_cv_header_stdbool_h = yes; then + +$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +$as_echo_n "checking for uid_t in sys/types.h... " >&6; } +if ${ac_cv_type_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then : + ac_cv_type_uid_t=yes +else + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +$as_echo "$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +$as_echo "#define uid_t int" >>confdefs.h + + +$as_echo "#define gid_t int" >>confdefs.h + +fi + +ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" +case $ac_cv_c_int32_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int32_t $ac_cv_c_int32_t +_ACEOF +;; +esac + +ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT32_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + +ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" +case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; +esac + +ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT64_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + +ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" +if test "x$ac_cv_type_mode_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + + +# Use multithreading +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5 +$as_echo_n "checking for library containing pthread_create... " >&6; } +if ${ac_cv_search_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_pthread_create=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_pthread_create+:} false; then : + break +fi +done +if ${ac_cv_search_pthread_create+:} false; then : + +else + ac_cv_search_pthread_create=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5 +$as_echo "$ac_cv_search_pthread_create" >&6; } +ac_res=$ac_cv_search_pthread_create +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + as_fn_error $? "\"could not find libpthread\"" "$LINENO" 5 +fi + +# Support using libudev or libblkid for UUID lookup +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing udev_new" >&5 +$as_echo_n "checking for library containing udev_new... " >&6; } +if ${ac_cv_search_udev_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char udev_new (); +int +main () +{ +return udev_new (); + ; + return 0; +} +_ACEOF +for ac_lib in '' udev; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_udev_new=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_udev_new+:} false; then : + break +fi +done +if ${ac_cv_search_udev_new+:} false; then : + +else + ac_cv_search_udev_new=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_udev_new" >&5 +$as_echo "$ac_cv_search_udev_new" >&6; } +ac_res=$ac_cv_search_udev_new +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + for ac_header in libudev.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libudev.h" "ac_cv_header_libudev_h" "$ac_includes_default" +if test "x$ac_cv_header_libudev_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUDEV_H 1 +_ACEOF + +fi + +done + +fi + +ac_fn_c_check_header_mongrel "$LINENO" "blkid/blkid.h" "ac_cv_header_blkid_blkid_h" "$ac_includes_default" +if test "x$ac_cv_header_blkid_blkid_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing blkid_evaluate_tag" >&5 +$as_echo_n "checking for library containing blkid_evaluate_tag... " >&6; } +if ${ac_cv_search_blkid_evaluate_tag+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blkid_evaluate_tag (); +int +main () +{ +return blkid_evaluate_tag (); + ; + return 0; +} +_ACEOF +for ac_lib in '' blkid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_blkid_evaluate_tag=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_blkid_evaluate_tag+:} false; then : + break +fi +done +if ${ac_cv_search_blkid_evaluate_tag+:} false; then : + +else + ac_cv_search_blkid_evaluate_tag=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_blkid_evaluate_tag" >&5 +$as_echo "$ac_cv_search_blkid_evaluate_tag" >&6; } +ac_res=$ac_cv_search_blkid_evaluate_tag +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_BLKID_EVALUATE_TAG /**/" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing blkid_get_devname" >&5 +$as_echo_n "checking for library containing blkid_get_devname... " >&6; } +if ${ac_cv_search_blkid_get_devname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blkid_get_devname (); +int +main () +{ +return blkid_get_devname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' blkid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_blkid_get_devname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_blkid_get_devname+:} false; then : + break +fi +done +if ${ac_cv_search_blkid_get_devname+:} false; then : + +else + ac_cv_search_blkid_get_devname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_blkid_get_devname" >&5 +$as_echo "$ac_cv_search_blkid_get_devname" >&6; } +ac_res=$ac_cv_search_blkid_get_devname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +$as_echo "#define HAVE_BLKID_GET_DEVNAME /**/" >>confdefs.h + +fi + + +fi + + +fi + + + +# Checks for header files. +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" +if test "x$ac_cv_header_windows_h" = xyes; then : + +$as_echo "#define HAVE_WINDOWS_H /**/" >>confdefs.h + + WINLDADD=-static +fi + + + +ac_fn_c_check_header_compile "$LINENO" "winioctl.h" "ac_cv_header_winioctl_h" "#include +" +if test "x$ac_cv_header_winioctl_h" = xyes; then : + +$as_echo "#define HAVE_WINIOCTL_H /**/" >>confdefs.h + +fi + + +ac_fn_c_check_header_compile "$LINENO" "winsock.h" "ac_cv_header_winsock_h" "#include +" +if test "x$ac_cv_header_winsock_h" = xyes; then : + +$as_echo "#define HAVE_WINSOCK_H /**/" >>confdefs.h + +fi + + +ac_fn_c_check_header_compile "$LINENO" "winreg.h" "ac_cv_header_winreg_h" "#include +" +if test "x$ac_cv_header_winreg_h" = xyes; then : + +$as_echo "#define HAVE_WINREG_H /**/" >>confdefs.h + +fi + + +ac_fn_c_check_header_compile "$LINENO" "shlobj.h" "ac_cv_header_shlobj_h" "#include +" +if test "x$ac_cv_header_shlobj_h" = xyes; then : + +$as_echo "#define HAVE_SHLOBJ_H /**/" >>confdefs.h + +fi + + +# Checks for functions. +for ac_func in vprintf +do : + ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +for ac_func in setlocale getmntent getmntent_r getfsstat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" +if test "x$ac_cv_func_getline" = xyes; then : + $as_echo "#define HAVE_GETLINE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getline.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getline.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + $as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" gettimeofday.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS gettimeofday.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "getuid" "ac_cv_func_getuid" +if test "x$ac_cv_func_getuid" = xyes; then : + $as_echo "#define HAVE_GETUID 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getuid.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getuid.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes; then : + $as_echo "#define HAVE_LOCALTIME_R 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" localtime_r.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS localtime_r.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "pipe" "ac_cv_func_pipe" +if test "x$ac_cv_func_pipe" = xyes; then : + $as_echo "#define HAVE_PIPE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" pipe.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS pipe.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "readlink" "ac_cv_func_readlink" +if test "x$ac_cv_func_readlink" = xyes; then : + $as_echo "#define HAVE_READLINK 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" readlink.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS readlink.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "sleep" "ac_cv_func_sleep" +if test "x$ac_cv_func_sleep" = xyes; then : + $as_echo "#define HAVE_SLEEP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" sleep.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS sleep.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "symlink" "ac_cv_func_symlink" +if test "x$ac_cv_func_symlink" = xyes; then : + $as_echo "#define HAVE_SYMLINK 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" symlink.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS symlink.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "syslog" "ac_cv_func_syslog" +if test "x$ac_cv_func_syslog" = xyes; then : + $as_echo "#define HAVE_SYSLOG 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" syslog.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS syslog.$ac_objext" + ;; +esac + +fi + + + +ac_config_files="$ac_config_files Makefile src/Makefile doc/Makefile scripts/Makefile" + + +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, we kill variables containing newlines. +# 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. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}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 "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + 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}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $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} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# 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'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by vchanger $as_me 1.0.1, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + 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 + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +vchanger config.status 1.0.1 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +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=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + 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 || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + 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 + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #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. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # 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. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;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&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "$am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# 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 || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..9825144 --- /dev/null +++ b/configure.ac @@ -0,0 +1,71 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.63]) +AC_INIT([vchanger], [1.0.1], [jfisher@jaybus.com]) +AC_DEFINE([COPYRIGHT_NOTICE],["AC_PACKAGE_NAME Copyright (c) 2006-2015 Josh Fisher"],[Copyright notice]) +AC_CONFIG_SRCDIR([src]) +AC_CONFIG_LIBOBJ_DIR([src/compat]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE + +# Checks for programs. +AC_PROG_CC +AC_PROG_CXX +AC_PROG_INSTALL +AC_CHECK_TOOL([STRIP],[strip], []) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_C_TYPEOF +AC_HEADER_STDBOOL +AC_TYPE_PID_T +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_UID_T +AC_TYPE_INT32_T +AC_TYPE_UINT32_T +AC_TYPE_INT64_T +AC_TYPE_UINT64_T +AC_TYPE_MODE_T +AC_SYS_LARGEFILE + +# Use multithreading +AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR(["could not find libpthread"])]) +# Support using libudev or libblkid for UUID lookup +AC_SEARCH_LIBS([udev_new],[udev],[AC_CHECK_HEADERS([libudev.h])]) +AC_CHECK_HEADER([blkid/blkid.h], + [ AC_SEARCH_LIBS([blkid_evaluate_tag],[blkid], + [AC_DEFINE([HAVE_BLKID_EVALUATE_TAG],,[Have blkid_evaluate_tag function])], + [ AC_SEARCH_LIBS([blkid_get_devname],[blkid], + [AC_DEFINE([HAVE_BLKID_GET_DEVNAME],,[Have blkid_get_devname function])]) + ]) + ]) + +# Checks for header files. +AC_HEADER_DIRENT +AC_CHECK_HEADERS_ONCE([stdio.h stdlib.h string.h stdarg.h stddef.h]) +AC_CHECK_HEADERS_ONCE([time.h sys/time.h sys/timespec.h sys/wait.h limits.h locale.h syslog.h]) +AC_CHECK_HEADERS_ONCE([sys/types.h strings.h alloca.h sys/bitypes.h getopt.h utime.h sys/stat.h]) +AC_CHECK_HEADERS_ONCE([inttypes.h ctype.h errno.h unistd.h varargs.h mntent.h]) +AC_CHECK_HEADERS_ONCE([sys/param.h sys/mount.h sys/ucred.h grp.h pwd.h dirent.h fcntl.h]) +AC_CHECK_HEADERS_ONCE([sys/select.h optarg.h pthread.h libgen.h io.h signal.h]) +AC_CHECK_HEADER([windows.h], + [AC_DEFINE([HAVE_WINDOWS_H],,[have header windows.h]) + WINLDADD=-static]) +AC_SUBST(WINLDADD) +AC_CHECK_HEADER([winioctl.h], [AC_DEFINE([HAVE_WINIOCTL_H],,[have header winioctl.h])], [], [#include ]) +AC_CHECK_HEADER([winsock.h], [AC_DEFINE([HAVE_WINSOCK_H],,[have header winsock.h])], [], [#include ]) +AC_CHECK_HEADER([winreg.h], [AC_DEFINE([HAVE_WINREG_H],,[have header winreg.h])], [], [#include ]) +AC_CHECK_HEADER([shlobj.h], [AC_DEFINE([HAVE_SHLOBJ_H],,[have header shlobj.h])], [], [#include ]) +# Checks for functions. +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([setlocale getmntent getmntent_r getfsstat]) + +AC_REPLACE_FUNCS([getline gettimeofday getuid localtime_r pipe readlink sleep symlink syslog]) + +AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile scripts/Makefile]) + +AC_OUTPUT diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..4ebd5b3 --- /dev/null +++ b/depcomp @@ -0,0 +1,791 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2013-05-30.07; # UTC + +# Copyright (C) 1999-2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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, see . + +# 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 Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# Get the directory component of the given path, and save it in the +# global variables '$dir'. Note that this directory component will +# be either empty or ending with a '/' character. This is deliberate. +set_dir_from () +{ + case $1 in + */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; + *) dir=;; + esac +} + +# Get the suffix-stripped basename of the given path, and save it the +# global variable '$base'. +set_base_from () +{ + base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` +} + +# If no dependency file was actually created by the compiler invocation, +# we still have to create a dummy depfile, to avoid errors with the +# Makefile "include basename.Plo" scheme. +make_dummy_depfile () +{ + echo "#dummy" > "$depfile" +} + +# Factor out some common post-processing of the generated depfile. +# Requires the auxiliary global variable '$tmpdepfile' to be set. +aix_post_process_depfile () +{ + # If the compiler actually managed to produce a dependency file, + # post-process it. + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependency.h'. + # Do two passes, one to just change these to + # $object: dependency.h + # and one to simply output + # dependency.h: + # which is needed to avoid the deleted-header problem. + { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" + sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" + } > "$depfile" + rm -f "$tmpdepfile" + else + make_dummy_depfile + fi +} + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' +# Character ranges might be problematic outside the C locale. +# These definitions help. +upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ +lower=abcdefghijklmnopqrstuvwxyz +digits=0123456789 +alpha=${upper}${lower} + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The second -e expression handles DOS-style file names with drive + # letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ + | tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + aix_post_process_depfile + ;; + +tcc) + # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 + # FIXME: That version still under development at the moment of writing. + # Make that this statement remains true also for stable, released + # versions. + # It will wrap lines (doesn't matter whether long or short) with a + # trailing '\', as in: + # + # foo.o : \ + # foo.c \ + # foo.h \ + # + # It will put a trailing '\' even on the last line, and will use leading + # spaces rather than leading tabs (at least since its commit 0394caf7 + # "Emit spaces for -MD"). + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. + # We have to change lines of the first kind to '$object: \'. + sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" + # And for each line of the second kind, we have to emit a 'dep.h:' + # dummy dependency, to avoid the deleted-header problem. + sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + set_dir_from "$object" + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + set_base_from "$source" + tmpdepfile=$base.d + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir=$base.d-lock + trap " + echo '$0: caught signal, cleaning up...' >&2 + rmdir '$lockdir' + exit 1 + " 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0; do + # mkdir is a portable test-and-set. + if mkdir "$lockdir" 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rmdir "$lockdir" + break + else + # If the lock is being held by a different process, wait + # until the winning process is done or we timeout. + while test -d "$lockdir" && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + set_dir_from "$object" + set_base_from "$object" + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + make_dummy_depfile + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + set_dir_from "$object" + set_base_from "$object" + + if test "$libtool" = yes; then + # Libtool generates 2 separate objects for the 2 libraries. These + # two compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir$base.o.d # libtool 1.5 + tmpdepfile2=$dir.libs/$base.o.d # Likewise. + tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -ne 0; then + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + # Same post-processing that is required for AIX mode. + aix_post_process_depfile + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + echo >> "$depfile" # make sure the fragment doesn't end with a backslash + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this sed invocation + # correctly. Breaking it into two sed invocations is a workaround. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process the last invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed '1,2d' "$tmpdepfile" \ + | tr ' ' "$nl" \ + | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E \ + | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + | sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..5416284 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,2 @@ +man8_MANS = vchanger.8 +man5_MANS = vchanger.conf.5 diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..c33fc22 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,509 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man5dir = $(mandir)/man5 +am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man5_MANS) $(man8_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINLDADD = @WINLDADD@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +man8_MANS = vchanger.8 +man5_MANS = vchanger.conf.5 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-man5: $(man5_MANS) + @$(NORMAL_INSTALL) + @list1='$(man5_MANS)'; \ + list2=''; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list='$(man5_MANS)'; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man5 install-man8 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man5 uninstall-man8 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-man5 install-man8 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am uninstall-man uninstall-man5 uninstall-man8 + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/example-vchanger-udev.rules b/doc/example-vchanger-udev.rules new file mode 100644 index 0000000..b9c62d3 --- /dev/null +++ b/doc/example-vchanger-udev.rules @@ -0,0 +1,5 @@ +# This file contains udev rules for automounting drives assigned to vchanger +# +# Rules for magazine 0 (uuid:7b4526c4-d8e9-48ba-b227-f67f855a0dc7) +ACTION=="add",SUBSYSTEM=="block", ENV{ID_FS_UUID}=="7b4526c4-d8e9-48ba-b227-f67f855a0dc7", RUN+="/usr/libexec/vchanger/vchanger-launch-mount.sh 7b4526c4-d8e9-48ba-b227-f67f855a0dc7" +ACTION=="remove",SUBSYSTEM=="block", ENV{ID_FS_UUID}=="7b4526c4-d8e9-48ba-b227-f67f855a0dc7", RUN+="/usr/libexec/vchanger/vchanger-launch-umount.sh 7b4526c4-d8e9-48ba-b227-f67f855a0dc7" diff --git a/doc/vchanger-example.conf b/doc/vchanger-example.conf new file mode 100644 index 0000000..38ecfa5 --- /dev/null +++ b/doc/vchanger-example.conf @@ -0,0 +1,75 @@ +# Example vchanger 1.0.0 config file + +# +# Storage Resource Name of the Storage resource defined in bacula-dir.conf +# that is associated with this changer. +# [Default: 'vchanger' ] +#Storage Resource = "vchanger" + +# +# User User to run as when invoked by root. This must be the +# owner of the volume files controlled by this changer, and +# so will need to be the same user that bacula-sd runs as. +# [Default: none ] +User = bacula + +# +# Group Group to run as when invoked by root. This should be the +# owner group of the volume files controlled by this changer, +# and should also be the default group pf the user that +# bacula-sd runs as. +# [Default: none ] +group = tape + +# +# Work Dir Directory where virtual drive and magazine state information +# and symlinks for this changer are stored. +# [Default: /var/spool/vchanger/[StorageResource] ] +#work dir = "/var/spool/vchanger/vcahnger" + +# +# Logfile Path to log file for this changer. +# [Default: /var/log/vchanger/[StorageResource].log ] +#logfile = "/var/log/vchanger/vchanger.log" + +# +# Log Level Sets the level of detail being logged. An integer value from +# 0-7 is expected, where 7 logs the most detail. The levels +# correspond to LOG_EMERG - LOG_DEBUG. (See man 3 syslog) +# [Default: 3 (LOG_ERR) ] +#log_level = 3 + +# +# bconsole Sets the path to the bconsole binary that vchanger will run +# in order to send 'update slots' and 'label barcodes' commands +# to Bacula. To disable sending commands to Bacula, set +# bconsole="". +# [Default: "/usr/sbin/bconsole" ] +#bconsole = "/usr/sbin/bconsole" + +# +# bconsole config Path to the config file bconsole will use when vchanger +# invokes bconsole. By default, bconsole will be invoked +# without the -c flag. +# [Default: none ] +#bconsole config = /etc/bacula/bconsole.conf + +# +# Default Pool Name of the pool that new volumes created by vcahnger +# should be placed into when using bconsole to send a +# 'label barcodes' command. +# [Default: "Scratch" ] +#default pool = "Scratch" + +# +# Magazine [Required] Gives the list of magazines known to this changer. +# One or more magazine directives must be specified. A magazine +# may be specified as either a directory path or as the UUID +# of a filesystem partition. A magazine is specified by UUID +# by prefixing the string "UUID:" to the filesystem's UUID. +# For magazines specified by UUID, the mountpoint of the +# filesystem will be queried from the system. Note that vchanger +# does not attempt to mount the filesystem. +# [Default: none ] +#magazine = "uuid:4fcb1422-f15c-4d7a-8a32-a4dcc0af5e00" +#Magazine = "/mnt/backup2" diff --git a/doc/vchanger.8 b/doc/vchanger.8 new file mode 100644 index 0000000..5109406 --- /dev/null +++ b/doc/vchanger.8 @@ -0,0 +1,206 @@ +'\" t +.\" Title: vchanger +.\" Author: Josh Fisher +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 06/03/2015 +.\" Manual: vchanger Manual +.\" Source: vchanger 1.0.1 +.\" Language: English +.\" +.TH "VCHANGER" "8" "06/03/2015" "vchanger 1\&.0\&.1" "vchanger Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +vchanger \- Virtual disk\-based autochanger for Bacula network backup system +.SH "SYNOPSIS" +.sp +\fBvchanger\fR [\fIOptions\fR] config command [slot] [device] [drive] +.sp +\fBvchanger\fR [\fIOptions\fR] config CREATEVOLS mag_ndx count [start] +.sp +\fBvchanger\fR [\fIOptions\fR] config LISTMAGS +.sp +\fBvchanger\fR [\fIOptions\fR] config REFRESH +.SH "DESCRIPTION" +.sp +The \fBvchanger(8)\fR utility is used to emulate and control a virtual autochanger within the Bacula network backup system environment\&. Backup volumes stored on multiple disk filesystems are mapped to a single set of virtual slots, allowing an unlimited number of virtual drives for concurrent backup jobs and easy, unlimited scaling to any size by simply adding additional disks/filesystems, +.sp +Vchanger is primarily deigned for use with removable disk drives\&. Its ability to interact with Bacula and determine removable drive mount points through udev allow for plug\-n\-play operation when attaching and detaching removable disk drives\&. +.sp +The first argument, \fIconfig\fR, is required amd specifies the path to the \fBvchanger\&.conf(5)\fR configuration file of the autochanger to be commanded\&. +.sp +The second argument, \fIcommand\fR, is the Bacula Autochanger Interface command to perform\&. +.sp +The third argument, \fIslot\fR, is required for the LOAD, LOADED, and UNLOAD commands and gives the slot number of the volume to act upon\&. +.sp +The fourth argument, \fIdevice\fR, is required for the LOAD, LOADED, and UNLOAD commands\&. It normally specifies the device node of a tape drive for tape autochangers\&. For vcahnger, it is only required as a place holder, and its value is ignored\&. +.sp +The fifth argument, \fIdrive\fR, is required for the LOAD, LOADED, and UNLOAD commands and gives the zero\-based drive number to act upon\&. +.sp +Vchanger implements the commands defined by the Bacula Autochanger Interface specification\&. The following commands are supported\&. +.PP +\fBLIST\fR +.RS 4 +List slots, one line each, in the format slot:label\&. +.RE +.PP +\fBLOAD\fR \fIslot\fR \fIdevice\fR \fIdrive\fR +.RS 4 +Load the volume in slot +\fIslot\fR +into drive +\fIdrive\fR\&. +.RE +.PP +\fBLOADED\fR \fIslot\fR \fIdevice\fR \fIdrive\fR +.RS 4 +Print the slot number currently loaded into drive +\fIdrive\fR, or print +\fI0\fR +if the drive is unloaded\&. +.RE +.PP +\fBSLOTS\fR +.RS 4 +Print the number of slots\&. +.RE +.PP +\fBUNLOAD\fR \fIslot\fR \fIdevice\fR \fIdrive\fR +.RS 4 +Unload the volume currently loaded in drive +\fIdrive\fR\&. +.RE +.sp +Vchanger also implements the following undocumented comands +.PP +\fBLISTALL\fR +.RS 4 +List drive status followed by slot status, one line for each drive or slot, in the format type:number:status:label, where +\fItype\fR +is D for a drive or S for a slot, +\fInumber\fR +is the drive or slot number, +\fIstatus\fR +is E for empty or F for full, and +\fIlabel\fR +is the volume label (barcode)\&. +.RE +.sp +Additionally, the following extended commands are supported\&. +.PP +\fBCREATEVOLS\fR \fImag_ndx\fR \fIcount\fR \fI[start]\fR +.RS 4 +Create +\fIcount\fR +volume files on the magazine indexed by +\fImag_ndx\fR\&. Magazines are directories and/or filesystems that have been defined in the +\fBvchanger(5)\fR +configuration file given by +\fIconfig\fR\&. The magazine index is based on the order in which the Magazine directives appear in the configuration file, where index zero is the first occurrence\&. Optionally, +\fIstart\fR +specifies the minimum integer uniqueness number to append to a prefix string when generating filenames for the created volume files\&. The default is to use a uniqueness number greater than highest number currently used for any volume file on the selected magazine\&. +.RE +.PP +\fBLISTMAGS\fR +.RS 4 +List the status of all assigned magazines (directories and filesystems), one per line, in the format mag:count:start:mnt, where +\fImag\fR +is zero\-based index of the magazines specified in configuration file +\fIconfig\fR, +\fIcount\fR +is the number of volume files on that magazine, +\fIstart\fR +is the virtual slot number of the beginning of the range of slots mapped to the magazine\(cqs volume files, and +\fImnt\fR +is the magazine\(cqs directory/mountpoint if mounted, or blank if not currently mounted\&. +.RE +.PP +\fBREFRESH\fR +.RS 4 +Refresh state information for the autochanger defined by the configuration file +\fIconfig\fR, issuing an +\fIupdate slots\fR +command to Bacula if required\&. +.RE +.sp +\fBBacula Interaction\fR +.sp +By default, vcahgner will invoke bconsole and issue commands to Bacula when certain operator actions are needed\&. When anything happens that changes the current set of volume files being used, vchanger will invoke bconsole and issue an \fIupdate slots\fR command\&. For example, when the operator attaches a removable drive defined as one of the changer\(cqs magazines, the volume files on the removable drive must be mapped to virtual slots\&. Since the volume\-to\-slot mapping will have changed, Bacula will need to be informed of the change via the \fIupdate slots\fR command\&. The \fBREFRESH\fR command can be invoked to force vchanger to update state info and trigger \fIupdate slots\fR if needed\&. +.sp +Additionally, when new volumes are created with the \fBCREATEVOLS\fR command, vchanger will invoke bconsole and issue a \fIlabel barcodes\fR command to write volume labels on the newly created volume files\&. +.SH "COMMAND LINE OPTIONS" +.PP +\fB\-u, \-\-user\fR=\fIuid\fR +.RS 4 +Override the default user to run as when invoked by root\&. The default is normally specified in the configuration file given by +\fIconfig\fR\&. +.RE +.PP +\fB\-g, \-\-group\fR=\fIgid\fR +.RS 4 +Override the default group to run as when invoked by root\&. The default is normally specified in the configuration file given by +\fIconfig\fR\&. +.RE +.PP +\fB\-\-pool\fR=\fIpool\fR +.RS 4 +Overrides the name of the pool into which volumes created by the CREATEVOLS command will be placed when vchanger is configured to label new volumes by sending Bacula a +\fIlabel barcodes\fR +command\&. The default is given by the +\fIDefault Pool\fR +setting in the configuration file\&. +.RE +.PP +\fB\-l, \-\-label\fR=\fIprefix\fR +.RS 4 +Overrides the default volume label prefix when generating names for new volume files created by the CREATEVOLS command\&. The default is +\fIname_ndx\fR, where +\fIname\fR +is the autochanger name and +\fIndx\fR +is the magazine index\&. +.RE +.PP +\fB\-\-help\fR +.RS 4 +Displays command help for the vchanger command\&. +.RE +.PP +\fB\-\-version\fR +.RS 4 +Displays vchanger version information\&. +.RE +.SH "NOTES" +.sp +See the vchangerHowto\&.html file included in the doc directory of the source distribution for more detailed documentation\&. +.SH "SEE ALSO" +.sp +\fBvchanger\&.conf(5)\fR +.SH "COPYRIGHT" +.sp +Copyright 2006\-2015 Josh Fisher +.sp +This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. +.SH "AUTHOR" +.PP +\fBJosh Fisher\fR <\&jfisher@jaybus\&.com\&> +.RS 4 +Author. +.RE diff --git a/doc/vchanger.8.asciidoc b/doc/vchanger.8.asciidoc new file mode 100644 index 0000000..f3473ef --- /dev/null +++ b/doc/vchanger.8.asciidoc @@ -0,0 +1,180 @@ +VCHANGER(8) +=========== +Josh Fisher +:doctype: manpage +:man source: vchanger +:man version: 1.0.1 +:man manual: vchanger Manual + +NAME +---- +vchanger - Virtual disk-based autochanger for Bacula network backup system + + +SYNOPSIS +-------- +*vchanger* ['Options'] config command [slot] [device] [drive] + +*vchanger* ['Options'] config CREATEVOLS mag_ndx count [start] + +*vchanger* ['Options'] config LISTMAGS + +*vchanger* ['Options'] config REFRESH + + +DESCRIPTION +----------- +The *vchanger(8)* utility is used to emulate and control a virtual +autochanger within the Bacula network backup system environment. +Backup volumes stored on multiple disk filesystems are mapped to a +single set of virtual slots, allowing an unlimited number of virtual +drives for concurrent backup jobs and easy, unlimited scaling to any +size by simply adding additional disks/filesystems, + +Vchanger is primarily deigned for use with removable disk drives. Its +ability to interact with Bacula and determine removable drive mount +points through udev allow for plug-n-play operation when attaching +and detaching removable disk drives. + +The first argument, 'config', is required amd specifies the path to the +*vchanger.conf(5)* configuration file of the autochanger to be +commanded. + +The second argument, 'command', is the Bacula Autochanger Interface command +to perform. + +The third argument, 'slot', is required for the LOAD, LOADED, and UNLOAD +commands and gives the slot number of the volume to act upon. + +The fourth argument, 'device', is required for the LOAD, LOADED, and UNLOAD +commands. It normally specifies the device node of a tape drive for tape +autochangers. For vcahnger, it is only required as a place holder, and its +value is ignored. + +The fifth argument, 'drive', is required for the LOAD, LOADED, and UNLOAD +commands and gives the zero-based drive number to act upon. + +Vchanger implements the commands defined by the Bacula Autochanger +Interface specification. The following commands are supported. + +*LIST*:: + List slots, one line each, in the format slot:label. + +*LOAD* 'slot' 'device' 'drive':: + Load the volume in slot 'slot' into drive 'drive'. + +*LOADED* 'slot' 'device' 'drive':: + Print the slot number currently loaded into drive 'drive', or print + '0' if the drive is unloaded. + +*SLOTS*:: + Print the number of slots. + +*UNLOAD* 'slot' 'device' 'drive':: + Unload the volume currently loaded in drive 'drive'. + +Vchanger also implements the following undocumented comands + +*LISTALL*:: + List drive status followed by slot status, one line for each + drive or slot, in the format type:number:status:label, where + 'type' is D for a drive or S for a slot, 'number' is the drive + or slot number, 'status' is E for empty or F for full, and + 'label' is the volume label (barcode). + +Additionally, the following extended commands are supported. + +*CREATEVOLS* 'mag_ndx' 'count' '[start]':: + Create 'count' volume files on the magazine indexed by 'mag_ndx'. + Magazines are directories and/or filesystems that have been + defined in the *vchanger(5)* configuration file given by 'config'. + The magazine index is based on the order in which the Magazine + directives appear in the configuration file, where index zero is + the first occurrence. Optionally, 'start' specifies the minimum + integer uniqueness number to append to a prefix string when + generating filenames for the created volume files. The default + is to use a uniqueness number greater than highest number + currently used for any volume file on the selected magazine. + +*LISTMAGS*:: + List the status of all assigned magazines (directories and + filesystems), one per line, in the format mag:count:start:mnt, + where 'mag' is zero-based index of the magazines specified in + configuration file 'config', 'count' is the number of volume + files on that magazine, 'start' is the virtual slot number + of the beginning of the range of slots mapped to the magazine's + volume files, and 'mnt' is the magazine's directory/mountpoint + if mounted, or blank if not currently mounted. + +*REFRESH*:: + Refresh state information for the autochanger defined by the + configuration file 'config', issuing an 'update slots' command to + Bacula if required. + +*Bacula Interaction* + +By default, vcahgner will invoke bconsole and issue commands to Bacula +when certain operator actions are needed. When anything happens that +changes the current set of volume files being used, vchanger will +invoke bconsole and issue an 'update slots' command. For example, +when the operator attaches a removable drive defined as one of the +changer's magazines, the volume files on the removable drive must be +mapped to virtual slots. Since the volume-to-slot mapping will have +changed, Bacula will need to be informed of the change via the +'update slots' command. The *REFRESH* command can be invoked to force +vchanger to update state info and trigger 'update slots' if needed. + +Additionally, when new volumes are created with the *CREATEVOLS* command, +vchanger will invoke bconsole and issue a 'label barcodes' command to +write volume labels on the newly created volume files. + +COMMAND LINE OPTIONS +-------------------- + +*-u, --user*='uid':: + Override the default user to run as when invoked by root. The default + is normally specified in the configuration file given by 'config'. + +*-g, --group*='gid':: + Override the default group to run as when invoked by root. The default + is normally specified in the configuration file given by 'config'. + +*--pool*='pool':: + Overrides the name of the pool into which volumes created by the + CREATEVOLS command will be placed when vchanger is configured to + label new volumes by sending Bacula a 'label barcodes' command. The + default is given by the 'Default Pool' setting in the configuration + file. + +*-l, --label*='prefix':: + Overrides the default volume label prefix when generating names for + new volume files created by the CREATEVOLS command. The default is + 'name_ndx', where 'name' is the autochanger name and 'ndx' is the + magazine index. + +*--help*:: + Displays command help for the vchanger command. + +*--version*:: + Displays vchanger version information. + + +NOTES +----- +See the vchangerHowto.html file included in the doc directory of the +source distribution for more detailed documentation. + + +SEE ALSO +-------- +*vchanger.conf(5)* + + +COPYRIGHT +--------- +Copyright 2006-2015 Josh Fisher + +This is free software; +See the source for copying conditions. +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. diff --git a/doc/vchanger.conf.5 b/doc/vchanger.conf.5 new file mode 100644 index 0000000..3586934 --- /dev/null +++ b/doc/vchanger.conf.5 @@ -0,0 +1,145 @@ +'\" t +.\" Title: vchanger.conf +.\" Author: Josh Fisher +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 06/03/2015 +.\" Manual: vchanger Manual +.\" Source: vchanger.conf 1.0.1 +.\" Language: English +.\" +.TH "VCHANGER\&.CONF" "5" "06/03/2015" "vchanger\&.conf 1\&.0\&.1" "vchanger Manual" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +vchanger.conf \- configuration file for *vchanger(8)* +.SH "SYNOPSIS" +.sp +/etc/vchanger/vchanger\&.conf +.SH "DESCRIPTION" +.sp +\fBvchanger(8)\fR is passed the path to a configuration file as its first positional parameter\&. The file contains keyword\-value pairs, specified by the free\-form syntax \fIkeyword\fR = \fIvalue\fR\&. Keywords are case\-insensitive and embedded whitespace is ignored\&. For example, "LOGLEVEL" is equivalent to "Log Level"\&. Values are case\-sensitive and embedded whitespace is preserved, however leading and trailing whitespace is ignored\&. Values may be one of the following types: +.PP +BOOLEAN +.RS 4 +The case insensitive strings "true", "yes", and "1" are accepted as a true value, and "false", "no", and "0" as a false value\&. +.RE +.PP +INTEGER +.RS 4 +A numeric integer value +.RE +.PP +PATH +.RS 4 +A filesystem path\&. If the path does not begin with a +\fI\*(Aq/\fR\*(Aq character, then the path is considered a relative path\&. The directory to which the path is relative is described for the relevant keyword in the +\fBCONFIGURATION SETTINGS\fR +section\&. +.RE +.PP +STRING +.RS 4 +A text string\&. The string may be enclosed in double quotes\&. A quoted string may also contain escape sequences\&. An escape sequence begins with the back slash character \(oq\e\(cq\&. Valid escape sequences are \ea, \eb, \en, \er, \et, \ev, \e\e, and \e", and are interpreted as in the C language\&. +.RE +.SH "CONFIGURATION SETTINGS" +.PP +\fBbconsole\fR = \fIPATH\fR +.RS 4 +Specifies the path to the bconsole utility used to interface with the Bacula console\&. If given as a relative path, standard shell path search semantics apply\&. Specifying the empty string "" disables the sending of commands to Bacula\&. The default is "bconsole"\&. +.RE +.PP +\fBbconsole config\fR = \fIPATH\fR +.RS 4 +Specifies the path to the bconsole configuration file to use when invoking bconsole\&. The path is passed to bconsole using its \-c flag\&. If the empty string "" is specified, then bconsole is invoked without the \-c flag\&. The default is ""\&. +.RE +.PP +\fBDefault Pool\fR = \fISTRING\fR +.RS 4 +Specifies the name of the pool into which newly created volumes should be placed when labeling the new volumes via bconsole\&. The default is "Scratch"\&. +.RE +.PP +\fBGroup\fR = \fISTRING\fR +.RS 4 +Specifies the group that +\fBvchanger(8)\fR +should run as when invoked by the root user\&. The default \-s "tape"\&. +.RE +.PP +\fBLogfile\fR = \fIPATH\fR +.RS 4 +Specifies the path to the vchanger logfile\&. If a relative path is specified, then it is relative to the directory defined by the +\fBWork Dir\fR +keyword\&. The default is a file name that is the string "\&.conf" appended to the value of the +\fIStorage Resource\fR +keyword in the +\fIWork Dir\fR +directory\&. +.RE +.PP +\fBLog Level\fR = \fIINTEGER\fR +.RS 4 +Specifies the amount of logging desired\&. The value is an integer between 0 and 7, inclusive, corresponding to the LOG_EMERG through LOG_DEBUG log levels defined in +\fBsyslog(3)\fR\&. +.RE +.PP +\fBMagazine\fR = (\fIPATH\fR or \fISTRING\fR) +.RS 4 +Specifies a directory or file system that contains volume files that the changer specified by the +\fBStorage Resource\fR +keyword may use\&. this keyword may appear more than once in the configuration file in order to specify multiple magazines\&. Mounted file systems may be specified by prepending the string "UUID:" (case insensitive) to the UUID of the file system\&. Otherwise, the value specifies the path to a directory\&. +.RE +.PP +\fBStorage Resource\fR = \fISTRING\fR +.RS 4 +Specifies the name of the Storage resource, defined in the Bacula Director daemon\*(Aq\*(Aqs configuration file (bacula\-dir\&.conf), that is associated with this changer\&. The default is "vchanger"\&. +.RE +.PP +\fBUser\fR = \fISTRING\fR +.RS 4 +Specifies the user that +\fBvchanger(8)\fR +should run as when invoked by the root user\&. The default is "bacula"\&. +.RE +.PP +\fBWork Dir\fR = \fIPATH\fR +.RS 4 +Specifies the path to the work directory +\fBvchanger(8)\fR +will use for this changer\&. The default is a sub\-directory of /var/spool/vchanger named as the value of the +\fBStorage Resource\fR +keyword\&. +.RE +.SH "NOTES" +.sp +See the vchangerHowto\&.html file included in the doc directory of the source distribution for more detailed documentation\&. +.SH "SEE ALSO" +.sp +\fBvchanger(8)\fR +.SH "COPYRIGHT" +.sp +Copyright 2006\-2015 Josh Fisher +.sp +This is free software; See the source for copying conditions\&. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE\&. +.SH "AUTHOR" +.PP +\fBJosh Fisher\fR <\&jfisher@jaybus\&.com\&> +.RS 4 +Author. +.RE diff --git a/doc/vchanger.conf.5.asciidoc b/doc/vchanger.conf.5.asciidoc new file mode 100644 index 0000000..378fb41 --- /dev/null +++ b/doc/vchanger.conf.5.asciidoc @@ -0,0 +1,120 @@ +VCHANGER.CONF(5) +================ +Josh Fisher +:doctype: manpage +:man source: vchanger.conf +:man version: 1.0.1 +:man manual: vchanger Manual + +NAME +---- +vchanger.conf - configuration file for *vchanger(8)* + +SYNOPSIS +-------- +/etc/vchanger/vchanger.conf + +DESCRIPTION +----------- +*vchanger(8)* is passed the path to a configuration file as its first +positional parameter. The file contains keyword-value pairs, specified +by the free-form syntax 'keyword' = 'value'. Keywords are case-insensitive +and embedded whitespace is ignored. For example, "LOGLEVEL" is equivalent +to "Log Level". Values are case-sensitive and embedded whitespace is +preserved, however leading and trailing whitespace is ignored. Values +may be one of the following types: + + BOOLEAN:: + The case insensitive strings "true", "yes", and "1" are accepted + as a true value, and "false", "no", and "0" as a false value. + INTEGER:: + A numeric integer value + PATH:: + A filesystem path. If the path does not begin with a ''/'' character, + then the path is considered a relative path. The directory to + which the path is relative is described for the relevant keyword + in the *CONFIGURATION SETTINGS* section. + STRING:: + A text string. The string may be enclosed in double quotes. A + quoted string may also contain escape sequences. An escape + sequence begins with the back slash character `\'. Valid escape + sequences are \a, \b, \n, \r, \t, \v, \\, and \", and are + interpreted as in the C language. + +CONFIGURATION SETTINGS +---------------------- +*bconsole* = 'PATH':: + Specifies the path to the bconsole utility used to interface with + the Bacula console. If given as a relative path, standard shell + path search semantics apply. Specifying the empty string "" disables + the sending of commands to Bacula. The default is "bconsole". + +*bconsole config* = 'PATH':: + Specifies the path to the bconsole configuration file to use when + invoking bconsole. The path is passed to bconsole using its -c + flag. If the empty string "" is specified, then bconsole is invoked + without the -c flag. The default is "". + +*Default Pool* = 'STRING':: + Specifies the name of the pool into which newly created volumes + should be placed when labeling the new volumes via bconsole. + The default is "Scratch". + +*Group* = 'STRING':: + Specifies the group that *vchanger(8)* should run as when invoked + by the root user. The default -s "tape". + +*Logfile* = 'PATH':: + Specifies the path to the vchanger logfile. If a relative path is + specified, then it is relative to the directory defined by the + *Work Dir* keyword. The default is a file name that is the string + ".conf" appended to the value of the 'Storage Resource' keyword in + the 'Work Dir' directory. + +*Log Level* = 'INTEGER':: + Specifies the amount of logging desired. The value is an integer + between 0 and 7, inclusive, corresponding to the LOG_EMERG through + LOG_DEBUG log levels defined in *syslog(3)*. + +*Magazine* = ('PATH' or 'STRING'):: + Specifies a directory or file system that contains volume files that + the changer specified by the *Storage Resource* keyword may use. this + keyword may appear more than once in the configuration file in order + to specify multiple magazines. Mounted file systems may be specified + by prepending the string "UUID:" (case insensitive) to the UUID of + the file system. Otherwise, the value specifies the path to a + directory. + +*Storage Resource* = 'STRING':: + Specifies the name of the Storage resource, defined in the Bacula + Director daemon''s configuration file (bacula-dir.conf), that is + associated with this changer. The default is "vchanger". + +*User* = 'STRING':: + Specifies the user that *vchanger(8)* should run as when invoked + by the root user. The default is "bacula". + +*Work Dir* = 'PATH':: + Specifies the path to the work directory *vchanger(8)* will use for + this changer. The default is a sub-directory of /var/spool/vchanger + named as the value of the *Storage Resource* keyword. + +NOTES +----- +See the vchangerHowto.html file included in the doc directory of the +source distribution for more detailed documentation. + + +SEE ALSO +-------- +*vchanger(8)* + + +COPYRIGHT +--------- +Copyright 2006-2015 Josh Fisher + +This is free software; +See the source for copying conditions. +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. diff --git a/doc/vchangerHowto.html b/doc/vchangerHowto.html new file mode 100644 index 0000000..cb86ccf --- /dev/null +++ b/doc/vchangerHowto.html @@ -0,0 +1,1845 @@ + + + + + + + + + + + + +

Vchanger Howto

+

Josh Fisher

+

<jfisher at jaybus dot com>

+

Revision History

+

Revision 1.0.1 2015-06-09

+

Documented changes related to version 1.0.1 of the + software. This is a minor bug fix release.

+

Revision 1.0.0 2015-04-09

+

Documented changes related to version 1.0.0 of the + software. This major version change includes significant changes including + a dynamic and unlimited number of virtual drives and virtual slots, + removal of meta-information files from magazine partitions, interaction + with Bacula via bconsole, udev support, and more.

+

Revision 0.8.6 2010-05-14

+

Documented changes related to version 0.8.6 of the + software.

+

Revision 0.8.5 2010-02-05

+

Documented changes related to version 0.8.5 of the + software.

+

Revision 0.8.4 2009-12-02

+

Documented changes related to version 0.8.4 of the + software.

+

Revision 0.8.3 2009-10-26

+

Documented changes related to version 0.8.3 of the + software, which includes specifying magazine partitions by UUID and the + addition of the LISTMAGS command.

+

Revision 0.8.2 2009-04-14

+

Fixed some config file typos in the howto examples.

+

Revision 0.8.1 2009-01-27

+

Documented addition of command line flags for specifying + uid and gid vchanger should run as when invoked by root. Fixed examples to + coincide with changes to the by-label-fix udev rules for multi-magazine + autochangers.

+

Revision 0.8.0 2008-10-01

+

Initial beta release

+

Table of Contents

+ +

1. Introduction

+

This document describes how to utilize disk storage, particularly + removable disk storage devices, as backup media for a virtual autochanger + to implement a backup solution using Bacula, + an open source network backup solution. Bacula can use many types of + backup devices, one of them being robotic tape libraries, also known as + autochangers. Bacula utilizes these devices through an interface known as + the Bacula +Autochanger + Interface. Because autochangers are controlled in various + proprietary ways, the Bacula Autochanger Interface provides a generalized + method of interfacing with these devices by issuing commands, (such as + LOAD a tape, UNLOAD a tape, etc.), to an external script or program that + in turn implements the device-specific method of carrying out the desired + action. Vchanger is such a program, implementing the Bacula Autochanger + Interface to act as a virtual autochanger, using files on disk storage in + place of tapes.

+

1.1 Copyright And License

+

This document, VchangerHOWTO, is Copyright (c) 2008-2015 by Josh Fisher. Permission is + granted to copy, distribute and/or modify this document under the terms of + the GNU Free Documentation License, Version 1.1 or any later version + published by the Free Software Foundation; with no Invariant Sections, + with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the + license is available at http://www.gnu.org/copyleft/fdl.html. +

+

1.2 Disclaimer

+

No liability for the contents of this document can be accepted. Use the + concepts, examples and information at your own risk. There may be errors + and inaccuracies which could damage to your system. Though this is highly + unlikely, proceed with caution. The author(s) do not accept responsibility + for your actions.

+

All copyrights are held by their respective owners, unless specifically + noted otherwise. Use of a term in this document should not be regarded as + affecting the validity of any trademark or service mark. Naming of + particular products or brands should not be seen as endorsements.

+

1.3 Credits / Contributors

+

Many thanks to those who have participated on the Vchanger +Users + e-mail list with bug reports, testing, and suggestions.

+

Thanks, also, to all those who frequent the Bacula + User's e-mail list, and of course to Kern Sibbald and the other Bacula developers.

+

Bacula® is a registered trademark of Kern Sibbald.

+

Windows® is a registered trademark of Microsoft Corporation in + the United States and other countries.

+

1.4 Feedback

+

Vchanger +Users + e-mail list hosted by Sourceforge should be used for feedback. + Otherwise, contact information for the author is available in the source + tarball.

+

2. Definitions

+

Bacula is an open source network backup solution. Much more + information about Bacula is available at the Bacula website http://www.bacula.org.

+

An autochanger is a backup storage device consisting of one or + more tape drives, a mechanical tape library where a number of tape + cartridges are stored, and an individually addressable robotic device + capable of physically moving tape cartridges between the tape library and + the tape drives. The tape library contains mechanical slots, each of which + can hold one tape cartridge. In most cases, the slots are located in one + or more mechanical magazines, (tape caddies), that can be inserted into + and removed from one or more or the tape library's magazine bays.

+

A virtual autochanger emulates a tape autochanger using disk + storage, rather than tapes. Note that in the strictest sense, vchanger is + not a tape library emulator, in that it does not implement a device driver + with SCSI command interface. Rather it utilizes an API implemented by + Bacula to manipulate autochangers.

+

A slot is a physical location in a tape library that may + contain one volume (ie. tape cartridge).

+

A magazine is a mechanical tape storage device having a number of + slots into which tape cartridges may be inserted. The tape library of many + autochangers consists of one or more removable magazines, allowing several + tapes at a time to be swapped into or out of the tape library.

+

A bay, or magazine bay, is a physical location in a + tape library into which a magazine (tape caddy) can be inserted.

+

A removable disk drive is a random access disk storage device + that is external to, or easily removable from, a computer system. Examples + are external drive enclosures that connect via USB, eSATA, and hot + swappable SCSI/SAS/SATA drive bays.

+

The term hot swappable refers to hardware devices that may be + attached to and removed from a running computer system.

+

A volume is a sequential stream of data written to a tape or + file that begins with a Bacula volume label that identifies the data + stream.

+

The term drive, unless otherwise stated, refers to one of an + autochanger's drives, a device capable of reading and writing data from/to + a single tape or volume file.

+

3. Overview

+

The Bacula Storage Daemon controls an autochanger by invoking a script or + program, passing it command line arguments defined by the Bacula +Autochanger + Interface. The interface defines a set of commands and associated + arguments to load and unload the autochanger's drives, determine which + volumes are available in the autochanger's slots, and to determine from + which slot a drive was loaded or if it is empty. The interface is an + abstraction, allowing Bacula to communicate with various different + autochanger hardware devices through the use of a common set of commands. + It is the script or program's responsibility to interpret these Bacula + Autochanger Interface commands and cause the underlying hardware to + perform the requested action. Vchanger is such a program, accepting Bacula + Autochanger Interface commands and treating a group of disk file systems + as a virtual autochanger. Rather than loading tapes from library slots + into tape drives, as the mtx-changer script does for tape autochanger + hardware, vchanger "loads" disk file volumes from virtual slots into + virtual drives by creating symlinks pointing to volume files located on + one or more filesystems or directories assigned to the virtual + autochanger.

+

Using autochanger interface commands, Bacula interacts with a vchanger + autochanger in exactly the same way as it interacts with a tape + autochanger. Therefore to understand how Bacula interacts with a vchanger + autochanger, it is necessary to first understand how Bacula interacts with + a tape autochanger. An autochanger is defined in the Bacula Storage Daemon + configuration file as an Autochanger + resource. The Autochanger + resource defines the Changer + Device to be the system file name (device node) of the tape + library's robot and the Changer + Command to be the command that Bacula will + invoke to perform Bacula Autochanger Interface commands. Normally this + command will be the mtx-changer script that is shipped with Bacula, of + course customized and/or configured to operate with the particular + autochanger hardware. Additionally, the Autochanger + resource defines a list of one or more Device + resources, (also defined in the Storage Daemon configuration), + that belong to the autochanger. Each of an autochanger's tape drives is + defined as a separate Device + resource. Each tape drive's Device + resource defines its Archive + Device to be the device node of one of the autochanger's tape + drives and its Drive + Index that defines which of the autochanger's tape drives that + particular device node pertains to. An example configuration for a two + drive autochanger is given below.

+
# /etc/bacula/bacula-sd.conf
Autochanger {
Name = tapechgr
Changer Device = /dev/sg3
Changer Command = "/etc/bacula/mtx-changer %c %o %S %a %d"
Device = tapechgr-0, tapechgr-1
}
Device {
Name = tapechgr-0
Drive Index = 0
Autochanger = yes
Archive Device = /dev/nst0
}
Device {
Name = tapechgr-1
Drive Index = 1
Autochanger = yes
Archive Device = /dev/nst1
}
+

When Bacula needs to load a tape from one of the library's slots into one + of its tape drives, it will invoke the Changer + Command, (the mtx-changer script), with positional parameters, + where parameter 1 is the Changer + Device, parameter 2 is the command to be performed ("LOAD" in + this case), parameter 3 is the library slot containing the tape to be + loaded, parameter 4 is the Archive + Device of the Device + resource (tape drive) to be loaded, and parameter 5 is the Drive + Index of the Device + resource to be loaded. Once the needed tape is loaded into a drive, Bacula + will open the device node specified by the Archive + Device (the device node of the tape drive) to read or write + volume data from or to the tape.

+

Since a vchanger autochanger is treated like a tape autochanger, the + configuration for a vchanger autochanger looks very much the same,

+
# /etc/bacula/bacula-sd.conf
Autochanger {
Name = vchgr
Changer Device = /etc/vchanger/vchgr.conf
Changer Command = "/usr/bin/vchanger %c %o %S %a %d"
Device = vchgr-0, vchgr-1
}
Device {
Name = vchgr-0
Drive Index = 0
Autochanger = yes
Archive Device = /var/spool/vchanger/vchgr/0
}
Device {
Name = vchgr-1
Drive Index = 1
Autochanger = yes
Archive Device = /var/spool/vchanger/vchgr/1
} +
+

One obvious difference is that vchanger is invoked as the Changer + Command in place of the mtx-changer script, and with the Changer + Device passed as parameter 1 being the path to a vchanger + configuration file, rather than the device node of a tape library robot. + The only other difference is the Archive + Device setting in each of the Device + resources. Rather than the device node of a physical tape drive, + the Archive Device + of a vchanger autochanger's Device + resource specifies the path to a symlink that will act as a + virtual drive. When vchanger is invoked with the LOAD command, it creates + this symlink pointing to the volume file associated with the requested + slot number. This slot number is an index into a + virtual-slot-to-volume-file map maintained by vchanger. Just like the tape + autochanger, once the needed volume is "loaded", (ie. the symlink has been + created), Bacula will open the device specified by the Archive + Device to read or write volume data, in this case a regular file + instead of a tape drive device node. In the Unix way of treating + everything as a file, that is really only a minor difference. Details of + the vchanger autochanger implementation are given in section + 4 below.

+

3.1. What About Bacula's Native Virtual + Autochanger Support?

+

A Device resource's + Archive Device directive + determines the i/o device that will be used to read or write volume data. + Bacula handles the opening of the path specified as the Archive + Device differently depending upon whether or not that path + specifies a filesystem directory. If a Device + resource's Archive + Device specifies a directory, then when that Device + is opened Bacula will open one of the files in that directory for + reading or writing. Otherwise, if the Archive + Device is not a directory, then Bacula will directly open the + path specified by the Archive + Device for reading or writing.

+

For a Device + where the Archive + Device is not a directory, there can only possibly be one volume + available for reading or writing at any one time. For example, a tape + drive can only have one tape loaded at a time. For a + Device resource where the Archive + Device is a directory there, can be many volumes available. + Though a filesystem directory may contain multiple volume files, and + unlike a tape drive, could allow multiple volumes to be opened + simultaneously, Bacula purposefully limits a Device + resource to reading or writing only one volume at a time. This + abstraction is a good thing! It allows the remainder of Bacula's complex, + multi-threaded logic to treat all Device + resources in the same, consistent way. One Device + may read or write only one volume at a time.

+

Because this single volume restriction is not technically necessary for a + disk filesystem directory, one could define several Device + resources, all specifying the same directory path as their Archive Device. + Each of these Device + resources could have one volume file opened at a time. This will + allow multiple volume files in that directory to be opened simultaneously, + but will also force the operator to manually allocate backup jobs across + the available Devices. + The Autochanger resource + provides a means to group multiple Devices + together into a single addressable resource. Jobs can then be + configured to write to the single Autochanger + resource and Bacula will automatically handle the selection of an + available Device from + the group of Devices + assigned to that Autochanger.

+

An Autochanger resource + also defines a Changer + Command and Changer + Device. Ordinarily, for a tape autochanger, the Changer + Device defines the device node of a robotic tape library device + that moves tapes between library slots and one or more tape drives, and + the Changer Command + specifies a script or program that Bacula invokes to command the robot to + move tapes between library slots and tape drives. + When the Changer + Command  and Changer + Device are both null, Bacula has special handling that allows an + Autochanger + resource to be used with multiple disk storage Device + resources as a disk-based virtual autochanger.

+

For example, the following placed in the Bacula Storage Daemon + configuration defines a "native" disk virtual autochanger named FileChgr1 + with two virtual drives. The two Device + resources (virtual drives) allow two volume files to be open at + the same time, and of course more than two Device + resources could be configured to allow as many virtual drives as + needed.

+
Autochanger {
+    Name = FileChgr1
+    Device = FileChgr1-Dev1, FileChgr1-Dev2
+    Changer Command = /dev/null
+    Changer Device = /dev/null
+}
+
+Device {
+    Name = FileChgr1-Dev1
+    Media Type = File1
+    Archive Device = /backups
+    LabelMedia = yes          # lets Bacula label unlabeled media
+    Random Access = Yes
+    AutomaticMount = yes
+    RemovableMedia = yes
+    AlwaysOpen = no
+    Maximum Concurrent Jobs = 5
+}
+
+Device {
+    Name = FileChgr1-Dev2
+    Media Type = File1
+    Archive Device = /backups
+    LabelMedia = yes          # lets Bacula label unlabeled media
+    Random Access = Yes
+    AutomaticMount = yes
+    RemovableMedia = yes
+    AlwaysOpen = no
+    Maximum Concurrent Jobs = 5
+}
+

Notice that both Device + resources specify the same Archive + Device and Media + Type. This is because the Storage + resource in the Director configuration may only specify a single + Media Type. A + volume is given the Media + Type of the Device + it is written with. Since a location may have several tape drives + of the same type, Bacula uses the Media + Type to determine which volumes may be loaded into which Devices. + This, for example, allows Bacula to load a LTO-5 tape into any available + LTO-5 tape drive, while preventing Bacula from attempting to load the + LTO-5 tape into a LTO-2 drive. The same applies to the native virtual + autochanger. A volume file in one Device's + directory would not be found in another Device's + directory, and so with each Device + having a different Archive + Device directory, it would also be necessary for the Devices + to have different Media + Types to prevent Bacula from attempting to load a Device + with a volume file that does not exist on its Archive + Device. That in turn means that all of the autochanger's Devices + could not be associated to a single Storage + resource in the + Director configuration, and so defeats the purpose.

+

3.2. Why vchanger?

+

Because Bacula currently requires a Storage + resource to specify a single Media + Type, the native virtual autochanger is, for practical purposes, + limited to utilizing a single directory as volume file storage. If volume + files are contained in multiple filesystems, such as removable drives, + then those filesystems can only be mounted at that directory one at a + time. With vchanger, an unlimited number of filesystems may be + simultaneously mounted at different mount point directories with all + volume files on all filesystems having the same Media + Type. This allows an unlimited number of simultaneously available + volume files and an unlimited number of Device + resources (virtual drives), where any volume file on any + filesystem can be "loaded" into any of the autochanger's Device + resources using only a single Storage + resource in the Bacula Director. This gives vchanger the + following advantages:

+
    +
  • Available volume storage space can be easily scaled by adding + additional filesystems or directories
  • +
  • Scaling available volume storage space requires no change to the + Bacula configuration and no restart or reload of any Bacula daemons
  • +
  • All volumes have the same Media Type and so can be moved between + filesystems without any need to update volume information in the Bacula + catalog.
  • +
  • Filesystems can be specified by UUID and vchanger will query the OS + for the mount point when needed. This allows any type of automounting to + be used and the filesystems to be mounted at arbitrary paths.
  • +
  • It is very restore friendly. When volumes needed for a restore are + located on different filesystems, for example on multiple removable disk + drives, all filesystems containing the volumes needed for a restore can + be mounted simultaneously, eliminating the need for operator + interventions to swap removable drives.
  • +
+

By default, vchanger supports integration with Bacula through issuing + commands via bconsole. Whenever a change is detected in the volume file to + virtual slot mapping, for example when a removable drive is attached or + detached, vchanger will issue an update + slots command to synchronize Bacula's view of the autochanger's + available volumes. Also, when vchanger is used to add volume files to an + autochanger, a label barcodes + command is automatically issued to label the new volumes.

+

Vchanger also automates the generation of udev rules and scripts that may + be used to automatically mount and unmount the filesystems defined in + autochanger configuration files. When a removable drive is attached or + detached, a script may be launched by udev to mount or unmount the drive's + partition and issue an update slots + command via bconsole. These udev rules and scripts allow the attaching and + detaching of  removable drives used by vchanger to be a true + plug-n-play operation.
+

+

4. Virtual Autochanger Implementation

+

Vchanger implements the following Bacula + Autochanger Interface commands:

+ + + + + + + + + + + + + + + + + + + + + + + + +
+

LIST

+
+

Lists the slots and barcodes of currently inserted volumes

+
+

LOAD

+
+

Loads a volume from a slot into a drive

+
+

LOADED

+
+

Returns the one-based slot number where the volume currently + loaded into a drive came from, or zero if the drive is unloaded.

+
+

SLOTS

+
+

Returns the number of slots in the autochanger

+
+

UNLOAD

+
+

Unloads a volume from a drive and moves it back into a slot

+
+

Vchanger also implements the following + undocumented command defined in mtx-changer since Bacula version 5.1.0:

+ + + + + + + + +
+

LISTALL

+
+

Lists status information for all drives and slots

+
+

Vchanger also implements three vchanger-specific + extended commands that are not part of the documented Bacula Autochanger + Interface:

+ + + + + + + + + + + + + + + + +
+

LISTMAGS

+
+

List the status of configured magazines

+
+

CREATEVOLS

+
+

Creates empty volume files on a magazine.

+
+

REFRESH

+
+

Cause vchanger to refresh virtual drive and magazine state and + communicate any changes to Bacula.

+
+

The Bacula + Storage Daemon calls vchanger with 5 positional parameters defined as:

+ + + + + + + + + + + + + + + + + + + + + + + + +
+

Param 1

+
+

Path given by the + Changer + Device directive + in the Autochanger + resource. For + vchanger, this should define the path to the + autochanger's  vchanger + configuration file.

+
+

Param 2

+
+

Bacula Autochanger Interface command to execute

+
+

Param 3

+
+

The one-based slot number that the command is to act upon

+
+

Param 4

+
+

Path given by the Archive Device + directive of the Device + resource corresponding to the drive number given in parameter 5 + (ignored by vchanger)

+
+

Param 5

+
+

The zero-based drive number that the command is to act upon

+
+

Each vchanger autochanger requires a unique + configuration file and work directory. The configuration file specifies + the location of its work directory, defines the directories and/or + filesystems that are to be used for volume file storage, and specifies the + Storage resource + name, (as defined by the Name + directive of the Storage + resource in bacula-dir.conf), that this autochanger is associated + with. An autochanger's work directory is where vchanger will keep virtual + drive and magazine state information and where the symlinks to volume + files will be created for loaded virtual drives.

+

4.1. Virtual Magazines

+

Virtual autochangers using vchanger treat the directories and filesystems + assigned to them as "virtual magazines", each able to contain a variable + number of volume files. This is analogous to the mechanical tape + magazines, (tape caddies), that many tape autochangers use. These tape + autochangers have one or more bays into which removable tape magazines can + be inserted. Each tape magazine contains a fixed number of slots into + which individual tape cartridges may be inserted. The principle difference + is that tape magazines have a fixed number of physical slots, whereas + vchanger virtual magazines have a variable and unlimited number of virtual + slots.

+

Virtual magazines are filesystems or directories that are assigned to an + autochanger by including Magazine directive lines in the vchanger + configuration file. The order in which the Magazine + directive lines appear in the configuration file  determines + which "virtual bay" the magazine is "inserted" into. The first occurrence + of the Magazine + directive in the vchanger configuration file specifies the magazine in bay + 0, the second occurrence specifies the magazine in bay 1, and so on. The + virtual bay is simply a zero-based index into the array of + filesystems/directories defined by Magazine + directives in the vchanger configuration file, and will be + referred to as a "magazine index".

+

The magazine index, or virtual bay, for a magazine is static and + determined solely by the order in which the Magazine + definitions appear in the vchanger configuration file. This + allows assigning integer numbers to the magazines to ease tracking of + multiple magazines. For example, consider an autochanger associated with a + Storage resource + in bacula-dir.conf named "changer1" for which we are using 10 RDX + cartridges as its virtual magazines. The default volume naming scheme used + by the CREATEVOLS command will name the first volume file created on the + first Magazine as + "changer1_0_0", the 23rd volume created on the second Magazine + as "changer1_1_22", and so on. When Bacula later requests a + volume that is on a RDX cartridge that is not currently mounted, this + volume file naming scheme will make it very easy to determine which RDX + cartridge needs to be attached in order to make the requested volume + available.

+

On most systems, filesystems to be used as magazines may be specified by + filesystem UUID, rather than mountpoint directory. This is useful on + systems where udev, Gnome Nautilus, other dbus-enabled automounters, and + etc. are used to automatically mount removable drives whenever they are + attached. Since vchanger is not normally running as root, it makes no + attempt to mount those filesystems. It only queries the system to + determine the current mount point of an already mounted filesystem.

+

Note that there is nothing special about the directories and filesystems + being used as magazines. A directory containing volume files created by + Bacula's native disk storage handling can be used as a vchanger magazine. + Likewise, a directory containing volumes created using a vchanger + autochanger can later be used with Bacula's native disk storage. Also, + individual volume files can be moved between the two. The only stipulation + is that the volume must have the same Media + Type as the bacula-dir.conf Storage + resource that it will be used with. If existing volumes are being moved to + a Storage + resource that has + a different Media + Type, then it will be necessary to manually update the Media + Type for those volumes.

+

4.2. Volume Files

+

A volume file is simply a regular file on one of the defined magazine + directories or file systems. A file cannot be used by Bacula until a + Bacula volume label has been written to it. Bacula supports bulk labeling + of volumes using barcodes. Many tape autochangers have barcode reader + hardware that can read the name of a tape cartridge from a barcode printed + on an adhesive paper label attached to the tape cartridge. The tape + autochanger can be commanded to read the barcodes and list the names of + the tapes it finds in each of its library slots. Bacula's label + barcodes command acquires this information from the tape + autochanger and writes a Bacula volume label to each unlabeled tape, + naming it according to the tape's barcode. Vchanger emulates a barcode + reader by using the volume file's filename as the barcode for that volume.

+

While it is recommended to use the default volume naming scheme + implemented by the CREATEVOLS command, it is not required and volume files + can have any filename. Just keep in mind that vchanger uses the volume + file's filename as its barcode label. This means that the filename must + match the volume label that was written to the file when the volume was + labeled. Volumes cannot be renamed by simply renaming the file to a + different filename. They would also have to have a new Bacula volume label + written to them.

+

4.3. Virtual Slots

+

Each time vchanger is invoked it maps the volume files on all attached + magazines to a virtual slot number. State information kept in the + autochanger's work directory is used to keep volume-to-slot mapping as + consistent as possible when removable disk drives are attached and + detached from the system. Drive state files contain information about the + volume last loaded into a virtual drive and are named 'drive_state-N', + where N is the drive number. Magazine state files contain information + about the magazines that were attached when vchanger was last invoked and + are named 'bay_state-N', where N is the magazine index.

+

Whenever anything happens to change the volume-to-slot mapping, Bacula + must be informed of the change. This is because Bacula tracks the contents + of autochanger slots in its catalog, as it must know which volumes are + available and where they are located in order to decide which volumes + should be assigned to which jobs and which volumes should be loaded into + which drives. Vchanger notifies Bacula when something changes by invoking + bconsole and issuing an update + slots command to cause Bacula to update its catalog info for the + affected autochanger.

+

Note that vchanger is not dependent on the state information kept in an + autochanger's work directory. Vchanger recalculates the current state of + virtual drives, bays, and slots whenever invoked. However, the state + information allows vchanger to only issue the update + slots command when a change is detected that requires it and + allows keeping the volume-to-slot mapping as consistent as possible.

+

4.4. Virtual Drives

+

Bacula treats volumes on a vchanger autochanger in the same way that it + treats tapes in a tape autochanger, by loading the volume it is going to + access into one of the autochanger's drives. Vchanger "loads" a virtual + drive by creating a symlink at a known location in the autochanger's work + directory that points to the volume file being loaded. A virtual drive is + unloaded by deleting that symlink. Vchanger supports a + dynamic and unlimited number of virtual drives. The number of + virtual drives actually used by Bacula will be determined in the Bacula + Storage Director's configuration file by the number of Device + resources assigned to the Autochanger + resource associated with the vchanger autochanger. Additional + virtual drives can be added by adding additional Device + resources to the Autochanger + resource in bacula-sd.conf and requires no further changes to the + vchanger configuration.

+

4.5. Vchanger Commands

+

The LIST command is performed by simply listing to stdout the calculated + slot-to-volume mapping, one line per virtual slot, in the format

+
slot:barcode
+

where slot is the virtual slot + number and barcode is the + filename of the volume mapped to that virtual slot. Because slot-to-volume + mapping is kept as consistent as possible, there may be virtual slots that + are empty, (ie. not currently mapped to a volume file). Empty slots will + be listed without a barcode string following the ':'.

+

The LISTALL command is similar to the LIST command except that it lists + drive status in addition to slot status to stdout. The output is in the + format

+
type:num:status:barcode
+

where type is 'D' for a drive + or 'S' for a slot, num is an + integer drive number for drives or slot number for slots, status + is 'F' for full or 'E' for empty, and barcode + is the filename of the associated volume file.

+

The LOAD command is performed by creating a symlink in the autochanger's + work directory that points to the volume file mapped to the requested + slot. The symlink is named as the integer drive number of the virtual + drive being loaded. For example, if the autochanger's work directory is + /var/spool/vchanger/changer1 and volume file /mnt/mag/volume1 is mapped to + virtual slot 10, then a LOAD command requesting that slot 10 be loaded + into drive 0 would result in the creation of a symlink named  + /var/spool/vchanger/changer1/0 that points to the file /mnt/mag/volume1.

+

The UNLOAD command is performed by deleting the symlink that was created + for a virtual drive by a previous LOAD command.

+

The LOADED command is performed by printing to stdout the slot number of + the virtual slot currently loaded into the requested drive, or zero if the + drive is not currently loaded.

+

The SLOTS command is performed by printing the current number of virtual + slots to stdout. For each autochanger, vchanger tracks the maximum number + of slots that have ever been simultaneously available on mounted magazines + in the dynamic.conf file in the autochanger's work directory. This is the + number reported by the SLOTS command. The number of slots defined for an + autochanger will increase as needed when multiple magazines are + simultaneously attached, but it will never decrease.

+

The LISTMAGS command is performed by printing one line of status + information for each magazine defined in the vchanger configuration file. + The format of a status line is:

+
bay:slots:start:mountpoint
+

where bay is the zero-based + index of the Magazine + line in the vchanger configuration file, slots + is the number of volume files currently existing on the magazine, + start is the starting slot + number of the range of virtual slots mapped to the magazine's volume + files, and mountpoint is the + magazine's directory or current filesystem mount point.

+

The CREATEVOLS command is used to add new volume files to a magazine and + cause Bacula to write volume labels to them.

+

The REFRESH command causes vchanger to refresh the current state of + magazines and virtual drives and issue a update + slots command via bconsole if needed. This command is intended to + be invoked when a magazine filesystem is mounted or unmounted, for example + by an automount script invoked by udev or by the operator after manually + mounting a magazine filesystem.

+

5. Installing vchanger

+

5.1. Installing from Source

+

On most POSIX systems, vchanger can be compiled and installed from source + as follows.

+

Unpack the gzip compressed tar archive.

+
[]$ tar -xzf vcahnger-1.0.0.tar.gz
+

Configure the build system and compile + vchanger

+
[]$ cd vchanger
+[]$ ./configure
+[]$ make
+

As root, install the executable and + documentation

+
[]$ su root
+[]# make install-strip
+

This will install the vchanger executable in + /usr/local/bin, udev automount scripts in /usr/local/libexec/vchanger, and + the documentation in /usr/local/share/doc/vchanger.

+

5.2. Installing from an RPM Package

+

x86_64 RPM packages for RHEL/Centos 6.x and RHEL/Centos 7.x, along with + the GPG signing key, are available for downloading from the vchanger + project page on SourceForge. An RPM install will create the /etc/vchanger + directory to hold autochanger configuration files, the /var/spool/vchanger + directory under which autochanger work directories will be created, and + the /var/log/vchanger directory under which autochanger log files will be + written.

+

The spec files used to create the RPM packages are included in the rpm + directory of the source distribution for those who would like to build an + RPM for other distributions or architectures.

+

5.3. Installing the Windows Version of + vchanger

+

On Windows, vchanger requires at least Windows Server 2008 or Vista and + will not run on earlier versions of Windows. A Windows installer is + available for downloading from SourceForge that will install a x86 or + x86_64 build of vchanger.

+

5.3.1. Installing the Windows Version from + Source

+

The Windows version was developed under Centos + 7.0 using the MinGW-w64 + (gcc-4.9.1) cross-compiler system. On a Linux system with MinGW-w64 + development tools installed, the Windows version can be built as follows:

+

Unpack the gzip compressed tar archive in your home directory.

+
[]$ cd ~
+[]$ tar -xzf /path/to/vcahnger-1.0.1.tar.gz
+

Configure the build system and cross-compile + vchanger

+
[]$ cd vchanger
+[]$ ./configure --host=x86_64-w64-mingw32 --build=`./config.guess` --prefix=./win32
+[]$ make
+[]$ make install-strip
+

The win32 executable, vchanger.exe, will be in + ~/vchanger/win32/bin and the Windows version documentation in + ~/vchanger/win32/share/doc/vchanger.

+

Building the Windows installer for vchanger requires the makensis + ustility from the NSIS project in addition to MinGW-w64. A shell script + named win32build in the source distribution will configure and build both + 32-bit and 64-bit Windows versions and then run makensis to create a + Windows installer that will install the 32-bit version on 32-bit versions + of Windows or the 64-bit version on 64-bit versions of Windows.

+

6. Preparing Removable Drives

+

6.1. Preparing Drives

+

Preparing removable drives for use by vchanger is fairly straight + forward. All that is needed is a filesystem partition on the removable + drive. Most external USB drives come with a NTFS filesystem installed and + using a GPT partition table. It is recommended that new removable drives + be partitioned and formatted to include a single partition and filesystem + encompassing the entire disk. Any read/write filesystem supported by the + OS may be used.

+

6.1.1. Setting Permissions for the + Magazine Filesystem

+

The Bacula Storage Daemon does not usually run as root. Since vchanger + will be invoked by the Storage Daemon, and so will run as the same user + that it does, permissions for magazine filesystems must be set to allow + read/write access to that user. This can be done by mounting the new + partition somewhere, then setting the appropriate permissions to give + read/write access to the user that the Storage Daemon runs as. It may also + be necessary to configure SELinux or AppArmour to allow the user that the + Storage Daemon runs as to read/write the magazine filesystems.

+

6.2. Determining the Magazine's + Filesystem UUID

+

On most POSIX systems, the blkid utility can be used to view the UUID of + a partition's filesystem.

+

On Windows, a filesystem UUID is known as a Volume Serial Number, (not to + be confused with the manufacturer's hardware serial number). Volume Serial + Numbers, are 8 hex digits with a '-' between the first 4 and last 4 hex + digits. This format differs from the UUIDs used by most POSIX systems, and + is due to Windows storing the Volume Serial Number internally as a 32-bit + binary number. This is not a problem, however, as Linux (and probably most + other POSIX systems) will happily use the Windows Volume Serial Number as + the filesystem UUID, though it is shorter in length. The simplest way to + get the Volume Serial Number is to open a Command Prompt window and issue + a DIR command on the removable drive's drive letter.

+

7. Mounting Removable Disk Drives

+

On Linux and other modern POSIX systems, removable drives are assigned a + device node when they are plugged in, but the OS does not by default mount + the drive partitions. Automounting is often handled by, for example, Gnome + Nautilus, + but this may not suffice for use with daemons, such as the Bacula Storage + Daemon that will normally invoke vchanger. The block storage device + containing the magazine's filesystem partition must, by some means, be + mounted before it can be used by vchanger. Since vchanger will be invoked + by the Bacula Storage Daemon, and will not ordinarily run with superuser + privileges, it does not itself attempt to mount filesystems.

+

7.1. udev and Hot-swappable Drives

+

Udev + is the subsystem that dynamically assigns device nodes to hot swappable + hardware devices when they are attached to a running system and frees + those device nodes when they are detached. In general, there is no + guarantee that a particular piece of hardware will be assigned a known + device node when it is plugged in. The device node that udev assigns will + depend on how many other devices are already attached and could change + every time the hot-swappable device is plugged in.

+

Fortunately, udev provides a way to create aliases to the device nodes it + assigns so that the device can be accessed using the fixed alias, + regardless of the actual device node assigned. With most Linux + distributions, the aliases are symlinks created dynamically by udev in + subdirectories of /dev/disk, and these symlinks point to the actual device + node assigned to the block storage device. In particular, symlinks are + created under /dev/disk/by-uuid such that the symlink name is the UUID of + the partition's filesystem. Consider, for example, a USB removable drive + with a partition containing a ext3 filesystem with UUID + 9667f83c-6150-44c7-b0d4-57564f174b35. When this USB drive is attached, + udev will assign a device node to it's partition and create the symlink + /dev/disk/by-uuid/9667f83c-6150-44c7-b0d4-57564f174b35 pointing to the + actual device node assigned. The device can then be accessed using the + known 'by-uuid' alias without having to discover the actual device node + assigned.

+

7.2. Manually Mounting Removable Drive + Partitions

+

One way to handle mounting and unmounting of removable drive partitions + is for the operator to manually mount the partitions when the removable + drive is attached and manually unmount the partitions before they are + detached. The mounting of magazine filesystems can be simplified by adding + the mounting information for the magazine filesystems to /etc/fstab, + identifying the partition by its filesystem UUID, and assigning the + filesystems in the vchanger configuration file by UUID. For example:

+
#/etc/fstab
...
# USB disks for vchanger +UUID=7b4526c4-d8e9-48ba-b227-f67f855a0dc7 /mnt/vchanger/mag0 ext4 defaults,noauto 1 2 +UUID=a4902c05-e47d-40e0-9db7-b3d03d08c266 /mnt/vchanger/mag1 ext4 defaults,noauto 1 2 +...
#eof

#/etc/vchanger/vchanger.conf
Storage Resource = vchanger
...
Magazine = UUID:7b4526c4-d8e9-48ba-b227-f67f855a0dc7
Magazine = UUID:a4902c05-e47d-40e0-9db7-b3d03d08c266 +#eof
+

The removable drive being used as magazine 0 could them be mounted and + made available with:

+
[]# mount /mnt/vchanger/mag0
[]# vchanger /etc/vchanger/vchanger.conf refresh
+

After use, the removable drive can then be removed using:

+
[]# umount /mnt/vchanger/mag0
[]# vchanger /etc/vchanger/vchanger.conf refresh
+

It is also possible, when manually mounting magazine partitions, to use + the mountpoint path in the Magazine + directive, rather than the UUID. When a magazine is specified by + path (rather than by UUID), vchanger assumes the magazine is mounted if + that path exists. However, if that directory path exists while the + magazine's partition is not mounted, then that directory will be part of + the underlying filesystem rather than the unmounted magazine partition's + filesystem. For this reason, specifying directory paths in Magazine + directives is only recommended for permanently mounted filesystems. + Filesystems that are not permanently mounted should be specified by UUID. +

+

7.3. Using udev To Mount Removable Drive + Partitions

+

Udev + responds to kernel messages to enable naming and handling of devices as + they are attached and detached from the system using a rule-based + approach. Rule files stored in /etc/udev/rules.d and /usr/lib/udev/rules.d + enable tailoring the naming and handling of hardware devices. Udev rules + make it possible to run short scripts in response to device events. With + the appropriate rules and the helper scripts provided with vchanger, the + attachment and detachment of removable disk drives used as vchanger + magazines can be made into a plug-n-play operation.

+

The vchanger-genudevrules + script will scan all vchanger configuration files in /etc/vchanger and + output to stdout the udev rules needed for each magazine that is specified + by filesystem UUID. These rules configure udev to execute scripts whenever + the partition with that filesystem UUID is attached or detached. The + scripts are included in the scripts directory of the vchanger source and + are usually installed into the /usr/libexec/vchanger directory.

+

The rule that matches when the device is attached invokes /usr/libexec/vchanger/vchanger-launch-mount.sh. + This is a very simple script with the sole purpose of lanching the + /usr/libexec/vchanger/vchanger-mount-uuid.sh script as a separate, + independent process. This is because udev does not invoke scripts in a + true shell and the scripts it invokes must execute very quickly and + without error The vchanger-mount-uuid.sh + script is supplied with a single argument, the UUID of the partition being + attached. If there is an fstab entry for the filesystem UUID, then the + partition is mounted using the mount point and mount options specified in + /etc/fstab. Otherwise, the partition is mounted at MOUNT_DIR/{uuid}, where + MOUNT_DIR is defined in a default parameter file named + /etc/default/vchanger (or /etc/sysconfig/vchanger). The + /etc/default/vchanger file may also define MOUNT_OPTIONS to be the mount + options that should be passed to the mount command via the -o flag. Note + that the same MOUNT_OPTIONS will be passed to the mount command for every + magazine file system. If there are magazine filesystems that require + different mount options, then they will have to be defined in /etc/fstab. + Finally, the script ends by invoking vchanger with the REFRESH command to + update state and issue a "update slots" command to Bacula via bconsole.

+

After adding or changing Magazine directives in a vchanger configuration + file, configure automounting through udev by:

+
[]# vchanger-genudevrules >/etc/udev/rules.d/96-vchanger.rules
[]# udevadm control --reload-rules
+

7.4. Using autofs To Mount Removable Drive + Partitions

+

The autofs daemon provides a way to + mount and unmount the magazine partitions on-the-fly as they are accessed. + This eliminates the need for manual mounting, but in a different way than + when using udev rules. autofs works by watching for accesses of a + particular path and mounting the device at that path on an as-needed + basis, then unmounting after an idle period. When using autofs to mount + the magazine partitions, the Magazine + directives in the vchanger configuration file will specify the + path to the mountpoint, rather than the filesystem UUID. Specifying paths + for Magazine directives + does not present a problem in this case, since autofs creates and deletes + the path dynamically as it mounts and unmounts the filesystem. For all + practical purpose, a mountpoint path controlled by autofs can be treated + as if it were permanently mounted.

+

An automount map file for use with vchanger is given below.

+
# /etc/auto.vchanger
+*          -fstype=auto,rw,sync       :/dev/disk/by-uuid/&
+# eof
+

Notice that 'sync' is specified in the flags that autofs will pass to the + mount command. This will turn off write caching and force all writes to + the magazine's filesystem to be written immediately to disk. Though it + reduces write performance, it helps to reduce the chance of data loss when + a removable drive is detached following a backup. Much better write + performance can be had by not specifying the sync option and being careful + not to unplug removable drives until after autofs unmounts them.

+

A line is then added to the /etc/auto.master file to tell autofs to pull + in the new auto.vchanger configuration:

+
# /etc/auto.master
+# ...
+/mnt/vchanger      /etc/auto.vchanger        --timeout=30
+# eof
+

After restarting the autofs daemon, whenever a file or directory with a + full path beginning with '/mnt/vchanger' is accessed, autofs will search + the map defined in the /etc/auto.vchanger file for a key matching the path + being accessed. In this case, the only key in /etc/auto.vchanger is the + wildcard '*', meaning any path name beginning with '/mnt/vchanger' will + match. Autofs then automatically mounts the device mapped to the wildcard + key at the path being accessed. The /etc/auto.vchanger map file specifies + the device to be mounted as /dev/disk/by-uuid/&. The '&' is + substituted for the key value. For example, when a program attempts to + access /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35 + (or any files or directories below it), the autofs daemon will look at + the auto.vchanger map for the key 9667f83c-6150-44c7-b0d4-57564f174b35 + and discover that it should mount + /dev/disk/by-uuid/9667f83c-6150-44c7-b0d4-57564f174b35 at + /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35 with mount options + '-fstype=auto,rw,sync'. After a period of 30 seconds of no activity, + autofs will automatically unmount the device.

+

Always make sure autofs is working properly + before continuing with setting up vchanger. If using the above autofs + config files, when you plug in a USB drive with filesystem UUID of, say, + 9667f83c-6150-44c7-b0d4-57564f174b35, you should be able to list its + contents with the command

+
[]# ls /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+

The Magazine directive in the vchanger + configuration file for the above example partition would be:

+
Magazine = /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+

7.5. Mounting Removable Drives On Windows

+

Microsoft Windows operating systems normally automount removable drive + partitions with recognized file systems. By default, the mountpoint for a + partition will be a drive letter (ie. E:). Unlike POSIX operating systems, + where '/' is the root of the single directory tree, Windows operating + systems use a multi-root directory structure where drive letters (and + network UNC base names) represent the roots of multiple, distinct + directory trees. When a removable drive is plugged in for the first time, + assuming the drive has a single partition, its partition will be mounted + at the next available drive letter. Windows remembers the drive letter + assignment for a partition so that it will be mounted at the same drive + letter when it is later re-attached, unless the drive letter is already + being used for another partition, in which case it will be mounted at the + next available drive letter. Note that it is not possible to assign the + same drive letter to two different removable drives simultaneously.

+

It is also possible, however, to mount a volume at a (empty) subdirectory + in another directory tree, as long as the volume mounted at the root of + that other directory tree is a NTFS volume. In fact, only the volume from + which Windows boots and volumes containing a virtual memory storage file + even require a drive letter at all. For removable drives, the drive letter + assignment can be deleted altogether and the partition always auto-mounted + at a directory in an NTFS directory tree. It should be noted that only the + mount point directory must be on an NTFS volume. The partition being + mounted may have a FAT32 file system or any other file system for which + there is a file system driver installed. See “Assign + a mount point folder path to a drive” for instructions on assigning + mountpoints for removable drive partitions. Like with drive letters, it is + not possible to assign the same mountpoint to more than one drive.

+

On Windows, magazine partitions should always be specified by UUID + (Volume Serial Number). This ensures that vchanger will be able to find + the partition's mountpoint without prior knowledge of which drive letter + or mountpoint Windows has currently assigned to the drive.

+

8. Configuring vchanger

+

Each vchanger autochanger is defined by a configuration file. Multiple + autochangers may be defined as long as each is given a unique name, its + own unique work directory, and its own unique configuration file. By + default, vchanger configuration files are placed in the /etc/vchanger + directory. The configuration files must be given permissions that + allow the user that the Bacula Storage Daemon runs as to have read access.

+

A vchanger configuration file consists of + keyword = value pairs. Comments are defined by a '#' character, and cause + text from the '#' until the next newline character to be ignored. Values + including whitespace or special characters must be enclosed in single or + double quotes. Special characters, including the quote character, + appearing inside of the quoted value must be escaped by prepending with a + '\' character. The following keywords are defined for an autochanger + configuration file:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Storage Resource

+
+

[Required] The name of the Storage resource, defined in the + Bacula Director configuration file, that is associated with this + autochanger.
+ Default: none

+
+

User

+
+

User to run as when vchanger is invoked by root. This user must + have read/write access to the work directory, magazine + directories, and volume files and should be the same user that the + Bacula Storage Daemon runs as.
+ Default: bacula

+
+

Group

+
+

Group to run as when vchanger is invoked by root. This group must + have access to the work directory, magazine directories, and + volume files and should be the same group that the Bacula Storage + Daemon runs as.
+ Default: tape

+
+

Work Dir

+
+

The directory where this autochanger will store virtual drive and + magazine state information and create symlinks to its volume + files.
+ Default: /var/spool/vchanger/{Storage Resource}

+
+

Logfile

+
+

Path to the logfile for this autochanger.
+ Default: /var/log/vchanger/{Storage Resource}.log

+
+

Log Level

+
+

The level of detail being logged. An integer value from 0-7 is + expected, where higher values increase logging. The levels + correspond to 'LOG_EMERG' through 'LOG_DEBUG' as defined for the + syslog() system call. See man 2 syslog for possible values.
+ Default: 3

+
+

bconsole

+
+

The path to the bconsole binary that vchanger will invoke to + issue 'update slots' and 'label barcodes' commands to Bacula. To + disable interaction with Bacula, set to the empty string.
+ Default: /usr/sbin/bconsole

+
+

bconsole config

+
+

The path to the configuration file to use when invoking bconsole.
+ Default: /etc/bacula/bconsole.conf

+
+

Default Pool

+
+

The default pool in which to add new volumes created by the + CREATEVOLS command.
+ Default: Scratch

+
+

Magazine

+
+

[Required] Defines either the path to a directory or the UUID of + a filesystem partition (prepended by the string “UUID:”) that is + to be used as a magazine containing volume files . The magazine + directive assigns a directory or partition to this autochanger. + This directive may appear multiple times to assign multiple + magazines.
+ Default: none

+
+

9. Initializing New + Magazines

+

After storage for a new magazine has been prepared, + it must be defined as an autochanger magazine. This is accomplished by + adding a Magazine + directive to the vchanger configuration file. For removable storage, the Magazine directive + should specify the filesystem UUID (or the mountpoint path if using + autofs). If a directory on permanently mounted fixed-disk storage is being + used as a magazine, then the Magazine + directive should specify the directory path. In either case, the + filesystem or directory must by writable by the user that Bacula Storage + Daemon runs as. The LISTMAGS vchanger command can be used to determine + that the magazine has been defined.

+

Once defined as an autochanger magazine, it is necessary to create volume + files on the magazine. While this can be accomplished manually by creating + empty files on the magazine and then labeling them from within bconsole + using the label + barcodes command, to make + adding volume files to a magazine easier and to facilitate a consistent + naming scheme, vchanger implements the CREATEVOLS command as:

+
vchanger config_file CREATEVOLS mag_bay count [start] [--pool=pool_name] [--label=prefix_string]
+

CREATEVOLS provides an easy way to add new volume files to a magazine and + label them into an appropriate pool. Volume files can be added to a + magazine at any time. Appendix A covers details of the CREATEVOLS + command.

+

10. Testing vchanger

+

Vchanger may be tested by running it from the command line. You must + either invoke vchanger as root or else as the user:group specified in the + vchanger configuration file, (which must be the same user:group that the + Bacula Storage Daemon runs as). If invoked as root, vchanger will switch + users to run as the user:group specified in the vchanger configuration + file given in the first parameter.

+

For example purposes, an autochanger using vchanger with USB external + drives will be designed step by step. Initially, two USB drives will be + initialized. For each of the two drives, the output from the dmesg command + is used to determine the assigned block device, and the blkid command used + to determine the UUID of its ext4 filesystem. A vchanger configuration + file is defined with Magazine directives assigning the empty USB drive + partitions to an autochanger named vchanger-1.

+
# /etc/vchanger/vchanger-1.conf
+Storage Resource = vchanger-1
User = bacula
Group = tape
Magazine = UUID:9667f83c-6150-44c7-b0d4-57564f174b35 +Magazine = UUID:5039284a-4312-57d1-92c4-354710032c79 +#eof
+

This defines an autochanger associated with a bacula-dir.conf Storage + resource named vchanger-1, with the Bacula Storage Daemon running as user + bacula:tape, and using two filesystems on removable USB drives as its + magazines. The filesystems will be mounted using udev, and the automount + scripts in the scripts directory of the vchanger source have been + installed to /usr/libexec/vchanger and the vchanger-genudevrules script + installed to /usr/bin. The udev rules needed to automount the magazine + filesystems can be generated and added to the udev rules with:

+
[]# vchanger-genudevrules >/etc/udev/rules.d/96-vchanger.rules
[]# udevadm control --reload-rules
+

A directory is created under which udev will mount the filesystems. The + filesystems will be mounted at subdirectories of this directory using the + filesystem UUID string as the subdirectory name.

+
[]# mkdir /mnt/vchanger
[]# chown bacula:tape /mnt/vchanger
[]# chmod 750 /mnt/vchanger
[]# echo "MOUNT_DIR=/mnt/vchanger" >/etc/sysconfig/vchanger
[]# echo "MOUNT_OPTIONS= >>/etc/sysconfig/vchanger
+

Now, attaching the USB drives should cause udev to invoke the + vchanger-mount-uuid.sh script to mount the filesystems as subdirectories + of the directory defined by the MOUNT_DIR variable specified in + /etc/sysconfig/vchanger (or /etc/default/vchanger).

+
[]# ls -1 /mnt/vchanger
+9667f83c-6150-44c7-b0d4-57564f174b35
+5039284a-4312-57d1-92c4-354710032c79
+
+

The owner and permissions must be set for the new filesystems in order to + give read/write access to the user that the Bacula Storage Daemon runs as:

+
[]# chown bacula:tape /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+[]# chmod 750 /mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+][# chown bacula:tape /mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79
+][# chmod 750 /mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79
+
+

The Storage resource that this autochanger is associated with is defined + in bacula-dir.conf as:

+
# /etc/bacula/bacula-dir.conf
...
# vchanger autochanger vchanger-1 +Storage { + Name = vchanger-1 + Address = 192.168.1.9 + SDPort = 9103 + Password = "password" + Device = usb-vchanger-1 + Media Type = File + Autochanger = yes; + Maximum Concurrent Jobs = 20 +} +... +#eof
+

The Device resource pointed to by the Storage resource is defined in + bacula-sd.conf as:

+
# /etc/bacula/bacula-sd.conf
...
# vchanger autochanger vchanger-1 +Autochanger { + Name = usb-vchanger-1 + Device = usb-vchanger-1-drive-0,usb-vchanger-1-drive-1 + Changer Command = "vchanger %c %o %S %a %d" + Changer Device = "/etc/vchanger/vchanger-1.conf" +} + +Device { + Name = usb-vchanger-1-drive-0 + Drive Index = 0 + Autochanger = yes; + Device Type = File + Media Type = File + Removable Media = no; + Random Access = yes; + Maximum Concurrent Jobs = 1 + Archive Device = "/var/spool/vchanger/vchanger-1/0" +} + +Device { + Name = usb-vchanger-1-drive-1 + Drive Index = 1 + Autochanger = yes; + Device Type = File + Media Type = File + Removable Media = no; + Random Access = yes; + Maximum Concurrent Jobs = 1 + Archive Device = "/var/spool/vchanger/vchanger-1/1" +} +... +#eof
+

After detaching both of the USB drives, list the status of the magazine + partitions currently in use by invoking (as root):

+
[]# vchanger /etc/vchanger/vchanger-1.conf listmags
+0:::
1:::
+

The output from the LISTMAGS + command shows that + neither of the magazine partitions is mounted, which is correct, since + neither of the two USB drives are attached. After attaching the USB drive + having the partition we defined in the first + Magazine directive, the output is:

+
[]# vchanger /etc/vchanger/vchanger-1.conf listmags
+0:::/mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+1:::
+

The output from the LISTMAGS command + now shows that the first defined magazine is mounted, but it has no + volumes. We can now add some + volumes with:

+
[]# vchanger /etc/vchanger/vchanger-1.conf createvols 0 2
+creating label 'vchanger-1_0_0'
+creating label 'vchanger-1_0_1'
+Created 2 volume files on magazine 0
+
+

Now the output from a LISTMAGS + command:

+
[]# vchanger /etc/vchanger/vchanger-1.conf listmags
+0:2:1:/mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35
+1:::
+

will show that the first defined magazine is mounted and has 2 volumes + mapped to virtual slots 1-2. We can issue the LIST command to see what + volumes the vchanger-1 autochanger has in its virtual slots.

+
[]# vchanger /etc/vchanger/vchanger-1.conf list
+1:vchanger-1_0_0
2:vchanger-1_0_1
+

This shows that two volume files are in slots 1 and 2. We can use + bconsole to see what Bacula thinks the autochanger status is.

+
[]# echo "status slots storage=vchanger-1 drive=0" | bconsole
+Connecting to Director 127.0.0.1:9101
+1000 OK: bacula-dir Version: 5.2.13 (19 February 2013)
+Enter a period to cancel a command.
+status slots storage=vchanger-1 drive=0
+Automatically selected Catalog: MyCatalog
+Using Catalog "MyCatalog"
+Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ...
+3306 Issuing autochanger "slots" command.
+Device "vchanger-1" has 2 slots.
+Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ...
+3306 Issuing autochanger "list" command.
+ Slot |   Volume Name    |   Status  |     Media Type       |      Pool          |
+------+------------------+-----------+----------------------+--------------------|
+    1 | vchanger-1_0_0   |    Append |                 File |            Scratch |
+    2 | vchanger-1_0_1   |    Append |                 File |            Scratch | 
+

This shows that the CREATEVOLS + command has created two volume files on the first magazine and has + successfully labeled them using the label barcodes command via + bconsole.

+

Now attach the second USB drive and add some volumes to it using:

+
[]# vchanger /etc/vchanger/vchanger-1.conf createvols 1 3
+creating label 'vchanger-1_1_0'
+creating label 'vchanger-1_1_1'
creating label 'vchanger-1_1_2'
Created 3 volume files on magazine 1 +
+

and confirm that the volumes were added as expected with:

+
[]# vchanger /etc/vchanger/vchanger-1.conf listmags
0:2:1:/mnt/vchanger/9667f83c-6150-44c7-b0d4-57564f174b35 +1:3:3:/mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79

[]# vchanger /etc/vchanger/vchanger-1.conf list +1:vchanger-1_0_0
2:vchanger-1_0_1
3:vchanger-1_1_0
4:vchanger-1_1_1
5:vchanger-1_1_2

[]# echo "status slots storage=vchanger-1 drive=0" | bconsole +Connecting to Director 127.0.0.1:9101 +1000 OK: bacula-dir Version: 5.2.13 (19 February 2013) +Enter a period to cancel a command. +status slots storage=vchanger-1 drive=0 +Automatically selected Catalog: MyCatalog +Using Catalog "MyCatalog" +Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ... +3306 Issuing autochanger "slots" command. +Device "vchanger-1" has 2 slots. +Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ... +3306 Issuing autochanger "list" command. + Slot | Volume Name | Status | Media Type | Pool | +------+------------------+-----------+----------------------+--------------------| + 1 | vchanger-1_0_0 | Append | File | Scratch |
2 | vchanger-1_0_1 | Append | File | Scratch | + 3 | vchanger-1_1_0 | Append | File | Scratch | + 4 | vchanger-1_1_1 | Append | File | Scratch | + 5 | vchanger-1_1_2 | Append | File | Scratch | +
+

If the first USB drive is now unplugged, the script invoked by udev + should unmount the first magazine partition and cause an update + slots command to be issued. This can be confirmed with:

+
[]# vchanger /etc/vchanger/vchanger-1.conf listmags
+0:::
+1:3:3:/mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79
+
+[]# vchanger /etc/vchanger/vchanger-1.conf list
+1:
+2:
+3:vchanger-1_1_0
+4:vchanger-1_1_1
+5:vchanger-1_1_2
+
+[]# echo "status slots storage=vchanger-1 drive=0" | bconsole
+Connecting to Director 127.0.0.1:9101
+1000 OK: bacula-dir Version: 5.2.13 (19 February 2013)
+Enter a period to cancel a command.
+status slots storage=vchanger-1 drive=0
+Automatically selected Catalog: MyCatalog
+Using Catalog "MyCatalog"
+Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ...
+3306 Issuing autochanger "slots" command.
+Device "vchanger-1" has 2 slots.
+Connecting to Storage daemon vchanger-1 at 192.168.1.9:9103 ...
+3306 Issuing autochanger "list" command.
+ Slot |   Volume Name    |   Status  |     Media Type       |      Pool          |
+------+------------------+-----------+----------------------+--------------------|
1*| | ? | ? | ? |
2*| | ? | ? | ? |
  3 | vchanger-1_1_0 | Append | File | Scratch | + 4 | vchanger-1_1_1 | Append | File | Scratch | + 5 | vchanger-1_1_2 | Append | File | Scratch | +
+

Let's now examine what happens when a volume file is "loaded" into a + virtual drive.

+
[]# vchanger /etc/vchanger/vchanger-1.conf load 3 /dev/null 0
+[]# ls -l /var/spool/vchanger/vchanger-1
+lrwxrwxrwx 1 bacula tape 29 Mar  1 16:46 0 -> /mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79/vchanger-1_1_0
+-rw-r----- 1 bacula tape 21 Mar  1 16:46 bay_state-1
+-rw-r----- 1 bacula tape 30 Mar  1 16:46 drive_state-0
+
+

The LOAD command created a symlink named '0' in the autochanger's work + directory that points to the file 'vchanger-1_1_0' in the filesystem + mounted at /mnt/vchanger/5039284a-4312-57d1-92c4-354710032c79, the volume + file that is mapped to virtual slot 3. The symlink named '0' is this + autochanger's drive 0. Notice that the path to this symlink was defined in + bacula-sd.conf as the Archive + Device for this autochanger's drive 0. When Bacula opens th the + symlink for reading or writing, it will actually be opening the volume + file that the symlink points to. 

+

The LOADED command can be used to check the status of a drive.

+
[]# vchanger /etc/vchanger/vchanger-1.conf loaded 0 /dev/null 0
3
[]# vchanger /etc/vchanger/vchanger-1.conf loaded 0 /dev/null 1
0
[]# vchanger /etc/vchanger/vchanger-1.conf loaded 0 /dev/null 13
0 +
+

The first command shows that drive 0 is loaded from slot 3. The zero + result of the second command shows that drive 1 is empty. The last line + shows that drive 13 is also empty. Although only drive 0 and drive 1 were + defined for this autochanger in bacula-sd.conf, vchanger commands will + operate on an unlimited number of virtual drives without requiring any + change in the vchanger configuration file. However, Bacula will only make + use of virtual drives defined by a Device + resource in bacula-sd.conf.

+

Finally, a virtual drive is unloaded using the UNLOAD command.

+
[]# vchanger /etc/vchanger/vchanger-1.conf unload 3 /dev/null 0
[]# ls -l /var/spool/vchanger/vchanger-1 +-rw-r----- 1 bacula tape 21 Mar 1 16:46 bay_state-1
{}# vchanger /etc/vchanger/vchanger-1.conf loaded 0 /dev/null 0
0
+

The virtual drive is unloaded by removing its corresponding symlink.

+

It is also possible to define mountpoints and mount options for the + magazine filesystems, (by UUID), in /etc/fstab. When the + vchanger-mount-uuid.sh script is invoked by udev, it will check for the + existence of an fstab entry for the magazine filesystem's UUID, and if it + exists will mount using the /etc/fstab entry rather than using the UUID as + the name of a subdirectory of the MOUNT_DIR directory defined in + /etc/sysconfig/vchanger.

+

11. Configuring Bacula To Use The + Autochanger

+

The virtual autochanger must be defined in Bacula by adding Autochanger and Device resources to Bacula's configuration + files.

+

11.1. Configuring the Bacula Storage Daemon

+

To configure the Bacula storage daemon (bacula-sd), add an Autochanger + resource and associated Device resource(es) to bacula-sd.conf. An + example of an autochanger with 2 virtual drives is:

+
# /etc/bacula/bacula-sd.conf
+# ...
+#----  local virtual autochanger with USB drive "magazines"
+Autochanger {
+  Name = usb-changer
+  Device = usb-changer-drive-0
+  Device = usb-changer-drive-1
+  Changer Command = "vchanger %c %o %S %a %d"
+  Changer Device = "/etc/vchanger/vc1.conf"
+}
+#---  drive 0 of the usb-changer autochanger
+Device {
+  Name = usb-changer-drive-0
+  DriveIndex = 0
+  Autochanger = yes;
+  DeviceType = File
+  MediaType = File
+  ArchiveDevice = /var/spool/vchanger/vc1/0
+  RemovableMedia = no;
+  RandomAccess = yes;
+}
+#---  drive 1 of the usb-changer autochanger
+Device {
+  Name = usb-changer-drive-1
+  DriveIndex = 1
+  Autochanger = yes;
+  DeviceType = File
+  MediaType = File
+  ArchiveDevice = /var/spool/vchanger/vc1/1
+  RemovableMedia = no;
+  RandomAccess = yes;
+}# ...
+# eof
+

In the Autochanger + resource, the Changer Device + value is the path to the vchanger configuration file for this autochanger. + The Changer Command value is the + command that Bacula will execute when it needs the autochanger to perform + some function, (like loading a volume). Here, we have installed vchanger + in /usr/bin, and Bacula is going to pass the Changer + Device value (the path to the vchanger configuration file) in + parameter 1, the API command (load, unload, etc) in parameter 2, the slot + number for the command in parameter 3, the Archive + Device value from the Device + resource that has a Drive Index value + equal to the drive index for the command in parameter 4, and the drive + index for the command in parameter 5.

+

11.2. Configuring the Bacula Director

+

The Bacula Director is configured to use the virtual autochanger in + exactly the same way as it would be configured for a tape autochanger.

+
# /etc/bacula/bacula-dir.conf
+# ...
+# Local USB drive virtual autochanger
+Storage {
+  Name = vchanger-1   # same as 'Storage Resource' in the vchanger config file
+  Address = sd-server-address
+  Password = "secret_password"
+  Device = usb-changer  # name of the Autochanger resource in bacula-sd.conf
+  Media Type = File
+  Autochanger = yes;
+}
+# eof
+

Appendix A. vchanger Commands

+

A.1. LIST Command

+

Bacula + issues this command to an autochanger to list to stdout the “barcode + labels” of volumes in the autochanger's slots. Many tape autochanger + robots have barcode readers such that tapes can be affixed with an + adhesive barcode label that identifies the tape. This allows Bacula to + automate the process of creating volume labels by utilizing the + autochanger's barcode reader. Vchanger emulates barcodes for the volumes + in a virtual autochanger's slots by listing the names of volume files + mapped to each virtual slot. The empty string is listed for each slot + corresponding to an empty slot (a slot that is not currently mapped to a + volume file).

+

A.2. LISTALL Command

+

It is not clear that Bacula currently uses this command internally, and + it is not specified in the Bacula + Autochanger Interface documentation. Nevertheless, it is implemented + in Bacula's mtx-changer script since version 5.1.0 and is used by some + web-based admin utilities, so has been implemented in vchanger. This + command is similar to the LIST command except that it also lists current + drive status in addition to slot status.

+

A.3. LOAD Command

+

The load command is used to “load” a volume + file from a virtual slot into a virtual drive. A tape autochanger does + this by physically moving the tape located in the requested library slot + into a tape drive. Bacula reads and writes volume data from/to the tape + drive's device file. With vchanger, a filesystem symlink at a known path + is used as a virtual drive in place of a tape drive's device file. A + volume file is then loaded by making the target of that symlink point to + the volume file mapped to the requested slot.

+

Parameter 3 gives the autochanger slot number + of the volume to load. Parameter 4 gives the path to the device that + Bacula will read/write and is ignored by vchanger. Parameter 5 gives the + drive number of the virtual drive that the volume is to be loaded into.

+

A.4. LOADED Command

+

This command is issued to determine which + slot, if any, is loaded into a drive. If a drive is loaded, then the + virtual slot number corresponding to the loaded volume file is written to + stdout. If the drive is not loaded, the string “0” is written to stdout to + inform Bacula that the drive is not loaded.

+

A.5. SLOTS Command

+

This + command simply prints to stdout the maximum number of volume files that + the autochanger has ever had simultaneously available. For example, if 6 + USB drive filesystems are assigned as the autochanger's magazines, each + with 10 volume files, and the maximum number of USB drives that were ever + simultaneously attached is 3, then the SLOTS command will return 30. If + more storage is needed at some point and 4 of the USB drives are + simultaneously attached, then a SLOTS command will return 40. Bacula + issues this command to determine how many slots an autochanger has.

+

A.6. UNLOAD Command

+

Bacula issues this command to unload a volume + from a drive and move it back into a library slot. Vchanger accomplished + this by deleting the virtual drive's symlink.

+

A.7. CREATEVOLS Command

+

This is an extended command that is not + part of the Bacula +Autochanger + Interface API, and is + used to add volume files to a magazine filesystem and cause them to be + labeled with a Bacula volume label. The format of this command is

+
vchanger config_file createcols mag_ndx count [start_num] [--label=prefix] [--pool=pool_name]
+

where:

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

config_file
+

+
+

Path to the autochanger's configuration file.
+

+
+

mag_ndx
+

+
+

The zero-based index of the magazine where volume files are to be + created. The index refers to a Magazine directive in the + configuration file specified by config_file, where 0 is the first + Magazine directive, 1, is the second Magazine directive, etc.
+

+
+

count

+
+

The number of volume files to create.

+
+

start_num

+
+

The lowest integer to append to the prefix string when forming + unique volume file names. The default is -1. A negative value + causes  the uniqueness number appended to the prefix to be + greater than the currently highest number used for file names + beginning with the given prefix.

+
+

prefix

+
+

An optional prefix string used in naming the created volume + files. The default prefix string is the autochanger's name + concatenated with '_' plus the magazine index number.

+
+

pool_name

+
+

The name of the pool into which created volumes should be + labeled. The default is "Scratch".

+
+

When new empty volume files are added, vchanger will issue a label + barcodes command to Bacula via bconsole to cause Bacula to write + volume labels on the new volume files. Adding volumes to a magazine will + change the virtual slot to volume mapping and may increase the + autochanger's slot count (the value returned by the SLOTS command). For + this reason, vchanger will also issue the update + slots command to Bacula whenever new volume files are added.

+

A.8. LISTMAGS Command

+

This is an extended command that is not part of the Bacula +Autochanger + Interface API, and is used to list status information about the + autochanger's assigned magazines. The format of this command is

+
vchanger config_file listmags
+

where:

+ + + + + + + + +
+

config_file

+
+

Path to the autochanger configuration file

+
+

The contents of each magazine bay are written + to stdout, one line per bay. The format of an output line is:

+
mag_ndx:count:start_slot:mountpoint
+

where:

+ + + + + + + + + + + + + + + + + + + + +
+

mag_ndx

+
+

The zero-based index of the magazine

+
+

count

+
+

The number of volume files on the magazine

+
+

start_slot

+
+

The beginning of the ranges of contiguous virtual slots mapped to + the magazine's volume files.

+
+

mountpoint

+
+

The mountpoint/directory of a mounted magazine, else blank if not + mounted.

+
+

A.9. REFRESH Command

+

This is an extended command that is not part of the Bacula Autochanger + Interface API, and is used to instruct vchanger to scan attached magazines + and recalculate the virtual-slot-to-volume-file mapping, sending an update slots + command to Bacula if any changes are detected. In general, this command is + designed to be invoked from a shell script launched by a udev event or + other automount mechanism.

+ + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..377bb86 --- /dev/null +++ b/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# 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. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # 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 $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/missing b/missing new file mode 100755 index 0000000..cdea514 --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2012-06-26.16; # UTC + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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, see . + +# 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. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'automa4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/rpm/vchanger.el6.spec b/rpm/vchanger.el6.spec new file mode 100644 index 0000000..53daa50 --- /dev/null +++ b/rpm/vchanger.el6.spec @@ -0,0 +1,91 @@ +# +# Spec file for vchanger - RHEL 6 +# +Summary: A virtual autochanger for Bacula +Name: vchanger +Version: 1.0.1 +Release: 1.el6 +License: GPLv2 +Group: System Environment/Daemons +Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz +URL: http://vchanger.sourceforge.net +Vendor: Josh Fisher. +Packager: Josh Fisher +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Requires(post): /bin/mkdir, /bin/chown, /usr/bin/getent, /usr/sbin/useradd, /usr/sbin/groupadd + +%description +Vchanger implements a virtual autochanger for use with the Bacula open source +network backup system. Vchanger emulates a magazine-based tape autoloader +using disk file system mountpoints as virtual magazines and the files in +each virtual magazine as virtual tape volumes. Vchanger is primarily +designed to use an unlimited number of removable disk drives as an easily +scalable virtual autochanger and allow seamless removal of backups for +offsite storage. + +%prep +%setup -q -n %{name} + +%build +CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE" \ +%configure +make + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p ${RPM_BUILD_ROOT}%{_bindir} +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name} +mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5 +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man8 +mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}-%{version} +mkdir -m 0770 -p ${RPM_BUILD_ROOT}%{_localstatedir}/spool/%{name} +mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name} +make DESTDIR=${RPM_BUILD_ROOT} install-strip +install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%{_bindir}/* +%{_libexecdir}/%{name}/* +%doc %{_docdir}/%{name}-%{version}/AUTHORS +%doc %{_docdir}/%{name}-%{version}/ChangeLog +%doc %{_docdir}/%{name}-%{version}/COPYING +%doc %{_docdir}/%{name}-%{version}/INSTALL +%doc %{_docdir}/%{name}-%{version}/NEWS +%doc %{_docdir}/%{name}-%{version}/README +%doc %{_docdir}/%{name}-%{version}/ReleaseNotes +%doc %{_docdir}/%{name}-%{version}/vchanger-example.conf +%doc %{_docdir}/%{name}-%{version}/example-vchanger-udev.rules +%doc %{_docdir}/%{name}-%{version}/vchangerHowto.html +%{_mandir}/man5/* +%{_mandir}/man8/* +%config(noreplace) %{_sysconfdir}/sysconfig/vchanger + +%post +if [ $1 -eq 1 ] ; then + /usr/bin/getent group tape &>/dev/null || /usr/sbin/groupadd -r tape + /usr/bin/getent group bacula &>/dev/null || /usr/sbin/groupadd -r bacula + /usr/bin/getent passwd bacula &>/dev/null || /usr/sbin/useradd -r -g bacula -d %{_localstatedir}/spool/bacula -s /bin/bash bacula + if [ ! -d %{_localstatedir}/spool/vchanger ] ; then + /bin/mkdir -p -m 0770 %{_localstatedir}/spool/vchanger + /bin/chown bacula:tape %{_localstatedir}/spool/vchanger + fi + if [ ! -d %{_localstatedir}/log/vchanger ] ; then + /bin/mkdir -p -m 0755 %{_localstatedir}/log/vchanger + /bin/chown bacula:tape %{_localstatedir}/log/vchanger + fi + if [ ! -d %{_sysconfdir}/vchanger ] ; then + /bin/mkdir -p -m 0755 %{_sysconfdir}/vchanger + fi +fi + +%changelog +* Wed Jun 3 2015 Josh Fisher +- Updated to release 1.0.1 +* Fri Apr 3 2015 Josh Fisher +- Initial spec file diff --git a/rpm/vchanger.el7.spec b/rpm/vchanger.el7.spec new file mode 100644 index 0000000..4c2caf0 --- /dev/null +++ b/rpm/vchanger.el7.spec @@ -0,0 +1,91 @@ +# +# Spec file for vchanger - RHEL 7 +# +Summary: A virtual autochanger for Bacula +Name: vchanger +Version: 1.0.1 +Release: 1.el7 +License: GPLv2 +Group: System Environment/Daemons +Source: http://sourceforge.net/projects/vchanger/files/vchanger/%{version}/vchanger-%{version}.tar.gz +URL: http://vchanger.sourceforge.net +Vendor: Josh Fisher. +Packager: Josh Fisher +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Requires(post): /bin/mkdir, /bin/chown, /usr/bin/getent, /usr/sbin/useradd, /usr/sbin/groupadd + +%description +Vchanger implements a virtual autochanger for use with the Bacula open source +network backup system. Vchanger emulates a magazine-based tape autoloader +using disk file system mountpoints as virtual magazines and the files in +each virtual magazine as virtual tape volumes. Vchanger is primarily +designed to use an unlimited number of removable disk drives as an easily +scalable virtual autochanger and allow seamless removal of backups for +offsite storage. + +%prep +%setup -q -n %{name} + +%build +CFLAGS="%{optflags} -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE" \ +%configure +make + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p ${RPM_BUILD_ROOT}%{_bindir} +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name} +mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}/%{name} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man5 +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man8 +mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}-%{version} +mkdir -m 0770 -p ${RPM_BUILD_ROOT}%{_localstatedir}/spool/%{name} +mkdir -m 0755 -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name} +make DESTDIR=${RPM_BUILD_ROOT} install-strip +install -m 0644 scripts/vchanger.default ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/vchanger + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root,-) +%{_bindir}/* +%{_libexecdir}/%{name}/* +%doc %{_docdir}/%{name}-%{version}/AUTHORS +%doc %{_docdir}/%{name}-%{version}/ChangeLog +%doc %{_docdir}/%{name}-%{version}/COPYING +%doc %{_docdir}/%{name}-%{version}/INSTALL +%doc %{_docdir}/%{name}-%{version}/NEWS +%doc %{_docdir}/%{name}-%{version}/README +%doc %{_docdir}/%{name}-%{version}/ReleaseNotes +%doc %{_docdir}/%{name}-%{version}/vchanger-example.conf +%doc %{_docdir}/%{name}-%{version}/example-vchanger-udev.rules +%doc %{_docdir}/%{name}-%{version}/vchangerHowto.html +%{_mandir}/man5/* +%{_mandir}/man8/* +%config(noreplace) %{_sysconfdir}/sysconfig/vchanger + +%post +if [ $1 -eq 1 ] ; then + /usr/bin/getent group tape &>/dev/null || /usr/sbin/groupadd -r tape + /usr/bin/getent group bacula &>/dev/null || /usr/sbin/groupadd -r bacula + /usr/bin/getent passwd bacula &>/dev/null || /usr/sbin/useradd -r -g bacula -d %{_localstatedir}/spool/bacula -s /bin/bash bacula + if [ ! -d %{_localstatedir}/spool/vchanger ] ; then + /bin/mkdir -p -m 0770 %{_localstatedir}/spool/vchanger + /bin/chown bacula:tape %{_localstatedir}/spool/vchanger + fi + if [ ! -d %{_localstatedir}/log/vchanger ] ; then + /bin/mkdir -p -m 0755 %{_localstatedir}/log/vchanger + /bin/chown bacula:tape %{_localstatedir}/log/vchanger + fi + if [ ! -d %{_sysconfdir}/vchanger ] ; then + /bin/mkdir -p -m 0755 %{_sysconfdir}/vchanger + fi +fi + +%changelog +* Wed Jun 3 2015 Josh Fisher +- Updated to release 1.0.1 +* Fri Apr 3 2015 Josh Fisher +- Initial spec file diff --git a/scripts/Makefile.am b/scripts/Makefile.am new file mode 100644 index 0000000..3f1e8fe --- /dev/null +++ b/scripts/Makefile.am @@ -0,0 +1,4 @@ +vscriptdir=$(libexecdir)/vchanger +dist_vscript_SCRIPTS = vchanger-launch-mount.sh vchanger-mount-uuid.sh \ + vchanger-launch-umount.sh vchanger-umount-uuid.sh +dist_bin_SCRIPTS = vchanger-genudevrules diff --git a/scripts/Makefile.in b/scripts/Makefile.in new file mode 100644 index 0000000..d7d2e9f --- /dev/null +++ b/scripts/Makefile.in @@ -0,0 +1,498 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = scripts +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(dist_bin_SCRIPTS) $(dist_vscript_SCRIPTS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(vscriptdir)" +SCRIPTS = $(dist_bin_SCRIPTS) $(dist_vscript_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINLDADD = @WINLDADD@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +vscriptdir = $(libexecdir)/vchanger +dist_vscript_SCRIPTS = vchanger-launch-mount.sh vchanger-mount-uuid.sh \ + vchanger-launch-umount.sh vchanger-umount-uuid.sh + +dist_bin_SCRIPTS = vchanger-genudevrules +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu scripts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu scripts/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dist_binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) +install-dist_vscriptSCRIPTS: $(dist_vscript_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(dist_vscript_SCRIPTS)'; test -n "$(vscriptdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(vscriptdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(vscriptdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(vscriptdir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(vscriptdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-dist_vscriptSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(dist_vscript_SCRIPTS)'; test -n "$(vscriptdir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(vscriptdir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(SCRIPTS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(vscriptdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_vscriptSCRIPTS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-dist_binSCRIPTS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_binSCRIPTS uninstall-dist_vscriptSCRIPTS + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dist_binSCRIPTS \ + install-dist_vscriptSCRIPTS install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am \ + uninstall-dist_binSCRIPTS uninstall-dist_vscriptSCRIPTS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/scripts/vchanger-genudevrules b/scripts/vchanger-genudevrules new file mode 100644 index 0000000..9eb52b6 --- /dev/null +++ b/scripts/vchanger-genudevrules @@ -0,0 +1,28 @@ +#!/bin/bash +# +# vchanger-genudevrules ( vchanger v.1.0.1 ) 2015-06-03 +# +# Search all autochanger configuration files for magazines being defined +# by filesystem UUID and print to stdout the udev rules for launching +# mount and umount scripts for those filesystems whenever the corresponding +# disk drives are attached or detached from the system. +# +LEDIR=/usr/libexec/vchanger +echo "# This file contains udev rules to launch mount and umount scripts" +echo "# for magazines defined by filesystem UUID in the autochanger configuration" +echo "# files under /etc/vchanger." +echo "#" +echo "# This file was generated by the vchanger-genudevrules script." +echo "#" +for cf in `ls -1 /etc/vchanger/*.conf` ; do + for tmp in `cat ${cf} | grep -v "^#" | tr -d " \t" | grep -i "^magazine="` ; do + tmp=`echo $tmp | grep -i "^magazine=uuid:"` + if [ -n "$tmp" ]; then + tmp=`echo $tmp | cut -d ':' -f 2 | tr -d ' \t\r\n'` + uuid=${tmp,,} + echo "ACTION==\"add\",SUBSYSTEM==\"block\", ENV{ID_FS_UUID}==\"$uuid\", RUN+=\"$LEDIR/vchanger-launch-mount.sh $uuid\"" + echo "ACTION==\"remove\",SUBSYSTEM==\"block\", ENV{ID_FS_UUID}==\"$uuid\", RUN+=\"$LEDIR/vchanger-launch-umount.sh $uuid\"" + fi + done +done +exit 0 diff --git a/scripts/vchanger-launch-mount.sh b/scripts/vchanger-launch-mount.sh new file mode 100644 index 0000000..552662f --- /dev/null +++ b/scripts/vchanger-launch-mount.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# vchanger-launch-mount.sh ( vchanger v.1.0.1 ) 2015-06-03 +# +# This script is used to run the vchanger-mount-uuid.sh script in +# another [background] process launched by the at command in order +# to prevent delays when invoked by a udev rule. +# +VCHANGER_MOUNT=/usr/libexec/vchanger/vchanger-mount-uuid.sh +{ +$VCHANGER_MOUNT $1 +} & diff --git a/scripts/vchanger-launch-umount.sh b/scripts/vchanger-launch-umount.sh new file mode 100644 index 0000000..e4726bb --- /dev/null +++ b/scripts/vchanger-launch-umount.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# vchanger-launch-umount.sh ( vchanger v.1.0.1 ) 2015-06-03 +# +# This script is used to run the vchanger-umount-uuid.sh script in +# another [background] process launched by the at command in order +# to prevent delays when invoked by a udev rule. +# +VCHANGER_UMOUNT=/usr/libexec/vchanger/vchanger-umount-uuid.sh +{ +$VCHANGER_UMOUNT $1 +} & diff --git a/scripts/vchanger-mount-uuid.sh b/scripts/vchanger-mount-uuid.sh new file mode 100644 index 0000000..ad01fac --- /dev/null +++ b/scripts/vchanger-mount-uuid.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# +# vchanger-mount-uuid.sh ( vchanger v.1.0.1 ) 2015-06-03 +# +# This script is used to mount the filesystem having the +# UUID specified in parameter 1 at a fixed path. The path +# will be a subdirectory of the path given by the MOUNT_DIR +# environment variable, where the UUID is used as the +# subdirectory name. The MOUNT_DIR variable is sourced from +# /etc/default/vchanger or /etc/sysconfig/vchanger. Also, +# the MOUNT_OPTIONS variable may be set to specify additional +# options to pass through to the mount command. +# +# Generally, this script is designed to be invoked by a +# launcher script, vchanger-launch-mount.sh, that is itself +# launched directly by udev in response to a hotplug event. +# This is useful for headless systems that do not have an +# automount capability such as Gnome Nautilus, but have +# non-root daemons that require plug-n-play attachment of +# external disk drives. +# + +MOUNT_DIR="/mnt" +MOUNT_OPTIONS= +[ -f /etc/sysconfig/vchanger ] && . /etc/sysconfig/vchanger +[ -f /etc/default/vchanger ] && . /etc/default/vchanger +[ -d "$MOUNT_DIR" ] || exit 0 # mount directory does not exist + +# Parameter 1 specifies the UUID of the magazine +# to be mounted +uuid=${1,,} +[ -n "$uuid" ] || exit 0 # ignore invalid param + +# +# Return mountpoint of filesystem having UUID passed in param 1 +# or else empty if UUID not found in fstab +# +function check_fstab { + local uuid=${1,,} + cat /etc/fstab | grep "^UUID=" | while read lin; do + line=`echo $lin | sed -e "s/[[:space:]]\+/ /g"` + tmp=`echo $line | cut -s -d ' ' -f 1 | cut -s -d '=' -f 2` + fu=${tmp,,} + if [ "z$fu" == "z$uuid" ]; then + echo $line | cut -s -d ' ' -f 2 + return 0 + fi + done +} + +# Search all autochanger configuration files for a magazine +# definition matching the UUID in parameter 1 +for cf in `ls -1 /etc/vchanger/*.conf` ; do + for tmp in `cat ${cf} | grep -v "^#" | tr -d " \t" | grep -i "^magazine="` ; do + tmp=`echo $tmp | grep -i "^magazine=uuid:"` + if [ -n "$tmp" ] ; then + tmp=`echo $tmp | cut -d ':' -f 2 | tr -d ' \t\r\n'` + tmp=${tmp,,} + if [ "z$uuid" == "z$tmp" ] ; then + # param 1 UUID matches a magazine filesystem + mdir=$(check_fstab $uuid) + if [ -n "$mdir" ]; then + # filesystem has UUID entry in fstab, so use it + if [ ! -d $mdir ]; then + mkdir -p $mdir &>/dev/null + [ -d $mdir ] || exit 0 # cannot create mountpoint dir + chmod 0750 $mdir + fi + mount $mdir + [ $? -eq 0 ] || exit 0 + /usr/bin/vchanger $cf refresh + exit 0 + fi + # Mount under configured MOUNT_DIR + if [ ! -d $MOUNT_DIR/$uuid ]; then + mkdir -p $MOUNT_DIR/$uuid &>/dev/null + [ -d $MOUNT_DIR/$uuid ] || exit 0 # cannot create mountpoint dir + chmod 0750 $MOUNT_DIR/$uuid + fi + echo checking dev + [ -e /dev/disk/by-uuid/$uuid ] || exit 0 # udev has no by-uuid symlinks + mount $MOUNT_OPTIONS /dev/disk/by-uuid/$uuid $MOUNT_DIR/$uuid &>/dev/null + if [ $? -eq 0 ] ; then + # On successful mount, cause update slots to be issued in bconsole + /usr/bin/vchanger $cf refresh + fi + exit 0 + fi + fi + done +done +exit 0 + \ No newline at end of file diff --git a/scripts/vchanger-umount-uuid.sh b/scripts/vchanger-umount-uuid.sh new file mode 100644 index 0000000..d26712b --- /dev/null +++ b/scripts/vchanger-umount-uuid.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# +# vchanger-umount-uuid.sh ( vchanger v.1.0.1 ) 2015-06-03 +# +# This script is used to unmount the filesystem having the +# UUID specified in parameter 1. The mountpoint path +# will be a subdirectory of the path given by the MOUNT_DIR +# environment variable, where the UUID is used as the +# subdirectory name. The MOUNT_DIR variable is sourced from +# /etc/default/vchanger or /etc/sysconfig/vchanger. +# +# Generally, this script is designed to be invoked by a +# launcher script, vchanger-launch-umount.sh, that is itself +# launched directly by udev in response to a hotplug event. +# This is useful for headless systems that do not have an +# automount capability such as Gnome Nautilus, but have +# non-root daemons that require plug-n-play attachment of +# external disk drives. +# + +MOUNT_DIR="/mnt/vchanger" +MOUNT_OPTIONS= +[ -f /etc/sysconfig/vchanger ] && . /etc/sysconfig/vchanger +[ -f /etc/default/vchanger ] && . /etc/default/vchanger +[ -d "$MOUNT_DIR" ] || exit 0 # mount directory does not exist + +# Parameter 1 specifies the UUID of the magazine +# to be unmounted +uuid=${1,,} +[ -n "$uuid" ] || exit 0 # ignore invalid param + +# +# Return mountpoint of filesystem having UUID passed in param 1 +# or else empty if UUID not found in fstab +# +function check_fstab { + local uuid=${1,,} + cat /etc/fstab | grep "^UUID=" | while read lin; do + line=`echo $lin | sed -e "s/[[:space:]]\+/ /g"` + tmp=`echo $line | cut -s -d ' ' -f 1 | cut -s -d '=' -f 2` + fu=${tmp,,} + if [ "z$fu" == "z$uuid" ]; then + echo $line | cut -s -d ' ' -f 2 + return 0 + fi + done +} + +# Search all autochanger configuration files for a magazine +# definition matching the UUID in parameter 1 +for cf in `ls -1 /etc/vchanger/*.conf` ; do + for tmp in `cat ${cf} | grep -v "^#" | tr -d " \t" | grep -i "^magazine="` ; do + tmp=`echo $tmp | grep -i "^magazine=uuid:"` + if [ -n "$tmp" ] ; then + tmp=`echo $tmp | cut -d ':' -f 2 | tr -d ' \t\r\n'` + tmp=${tmp,,} + if [ "z$uuid" == "z$tmp" ] ; then + # param 1 UUID matches a magazine filesystem + mdir=$(check_fstab $uuid) + if [ -n "$mdir" ]; then + # filesystem has UUID entry in fstab, so umount it + [ -d $mdir ] || exit 0 # mountpoint not found + umount $mdir &>/dev/null + /usr/bin/vchanger $cf refresh + exit 0 + fi + # Unmount from configured MOUNT_DIR + [ -d $MOUNT_DIR/$uuid ] || exit 0 # mountpoint not found + umount $MOUNT_DIR/$uuid &>/dev/null + /usr/bin/vchanger $cf refresh + exit 0 + fi + fi + done +done +exit 0 diff --git a/scripts/vchanger.default b/scripts/vchanger.default new file mode 100644 index 0000000..c08d8bc --- /dev/null +++ b/scripts/vchanger.default @@ -0,0 +1,2 @@ +MOUNT_DIR=/mnt/vchanger +MOUNT_OPTIONS= diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..d1805b1 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = foreign +AM_CFLAGS = -DLOCALSTATEDIR='"${localstatedir}"' +AM_CXXFLAGS = -DLOCALSTATEDIR='"${localstatedir}"' +AM_LDFLAGS = @WINLDADD@ +bin_PROGRAMS = vchanger +vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \ + compat/localtime_r.c \ + compat/readlink.c \ + compat/symlink.c compat/sleep.c compat/syslog.c \ + win32_util.c uuidlookup.c bconsole.cpp \ + tstring.cpp inifile.cpp mypopen.cpp \ + vconf.cpp loghandler.cpp errhandler.cpp \ + util.cpp changerstate.cpp diskchanger.cpp \ + vchanger.cpp diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..4d70f0c --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,722 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = vchanger$(EXEEXT) +subdir = src +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_vchanger_OBJECTS = getline.$(OBJEXT) gettimeofday.$(OBJEXT) \ + localtime_r.$(OBJEXT) readlink.$(OBJEXT) symlink.$(OBJEXT) \ + sleep.$(OBJEXT) syslog.$(OBJEXT) win32_util.$(OBJEXT) \ + uuidlookup.$(OBJEXT) bconsole.$(OBJEXT) tstring.$(OBJEXT) \ + inifile.$(OBJEXT) mypopen.$(OBJEXT) vconf.$(OBJEXT) \ + loghandler.$(OBJEXT) errhandler.$(OBJEXT) util.$(OBJEXT) \ + changerstate.$(OBJEXT) diskchanger.$(OBJEXT) \ + vchanger.$(OBJEXT) +vchanger_OBJECTS = $(am_vchanger_OBJECTS) +vchanger_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(vchanger_SOURCES) +DIST_SOURCES = $(vchanger_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINLDADD = @WINLDADD@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +AM_CFLAGS = -DLOCALSTATEDIR='"${localstatedir}"' +AM_CXXFLAGS = -DLOCALSTATEDIR='"${localstatedir}"' +AM_LDFLAGS = @WINLDADD@ +vchanger_SOURCES = compat/getline.c compat/gettimeofday.c \ + compat/localtime_r.c \ + compat/readlink.c \ + compat/symlink.c compat/sleep.c compat/syslog.c \ + win32_util.c uuidlookup.c bconsole.cpp \ + tstring.cpp inifile.cpp mypopen.cpp \ + vconf.cpp loghandler.cpp errhandler.cpp \ + util.cpp changerstate.cpp diskchanger.cpp \ + vchanger.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +vchanger$(EXEEXT): $(vchanger_OBJECTS) $(vchanger_DEPENDENCIES) $(EXTRA_vchanger_DEPENDENCIES) + @rm -f vchanger$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(vchanger_OBJECTS) $(vchanger_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bconsole.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changerstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskchanger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errhandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inifile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localtime_r.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loghandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mypopen.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sleep.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symlink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tstring.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uuidlookup.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vchanger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vconf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32_util.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +getline.o: compat/getline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getline.o -MD -MP -MF $(DEPDIR)/getline.Tpo -c -o getline.o `test -f 'compat/getline.c' || echo '$(srcdir)/'`compat/getline.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/getline.Tpo $(DEPDIR)/getline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/getline.c' object='getline.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getline.o `test -f 'compat/getline.c' || echo '$(srcdir)/'`compat/getline.c + +getline.obj: compat/getline.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getline.obj -MD -MP -MF $(DEPDIR)/getline.Tpo -c -o getline.obj `if test -f 'compat/getline.c'; then $(CYGPATH_W) 'compat/getline.c'; else $(CYGPATH_W) '$(srcdir)/compat/getline.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/getline.Tpo $(DEPDIR)/getline.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/getline.c' object='getline.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getline.obj `if test -f 'compat/getline.c'; then $(CYGPATH_W) 'compat/getline.c'; else $(CYGPATH_W) '$(srcdir)/compat/getline.c'; fi` + +gettimeofday.o: compat/gettimeofday.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gettimeofday.o -MD -MP -MF $(DEPDIR)/gettimeofday.Tpo -c -o gettimeofday.o `test -f 'compat/gettimeofday.c' || echo '$(srcdir)/'`compat/gettimeofday.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gettimeofday.Tpo $(DEPDIR)/gettimeofday.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/gettimeofday.c' object='gettimeofday.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gettimeofday.o `test -f 'compat/gettimeofday.c' || echo '$(srcdir)/'`compat/gettimeofday.c + +gettimeofday.obj: compat/gettimeofday.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gettimeofday.obj -MD -MP -MF $(DEPDIR)/gettimeofday.Tpo -c -o gettimeofday.obj `if test -f 'compat/gettimeofday.c'; then $(CYGPATH_W) 'compat/gettimeofday.c'; else $(CYGPATH_W) '$(srcdir)/compat/gettimeofday.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gettimeofday.Tpo $(DEPDIR)/gettimeofday.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/gettimeofday.c' object='gettimeofday.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gettimeofday.obj `if test -f 'compat/gettimeofday.c'; then $(CYGPATH_W) 'compat/gettimeofday.c'; else $(CYGPATH_W) '$(srcdir)/compat/gettimeofday.c'; fi` + +localtime_r.o: compat/localtime_r.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT localtime_r.o -MD -MP -MF $(DEPDIR)/localtime_r.Tpo -c -o localtime_r.o `test -f 'compat/localtime_r.c' || echo '$(srcdir)/'`compat/localtime_r.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/localtime_r.Tpo $(DEPDIR)/localtime_r.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/localtime_r.c' object='localtime_r.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o localtime_r.o `test -f 'compat/localtime_r.c' || echo '$(srcdir)/'`compat/localtime_r.c + +localtime_r.obj: compat/localtime_r.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT localtime_r.obj -MD -MP -MF $(DEPDIR)/localtime_r.Tpo -c -o localtime_r.obj `if test -f 'compat/localtime_r.c'; then $(CYGPATH_W) 'compat/localtime_r.c'; else $(CYGPATH_W) '$(srcdir)/compat/localtime_r.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/localtime_r.Tpo $(DEPDIR)/localtime_r.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/localtime_r.c' object='localtime_r.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o localtime_r.obj `if test -f 'compat/localtime_r.c'; then $(CYGPATH_W) 'compat/localtime_r.c'; else $(CYGPATH_W) '$(srcdir)/compat/localtime_r.c'; fi` + +readlink.o: compat/readlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readlink.o -MD -MP -MF $(DEPDIR)/readlink.Tpo -c -o readlink.o `test -f 'compat/readlink.c' || echo '$(srcdir)/'`compat/readlink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readlink.Tpo $(DEPDIR)/readlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/readlink.c' object='readlink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readlink.o `test -f 'compat/readlink.c' || echo '$(srcdir)/'`compat/readlink.c + +readlink.obj: compat/readlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT readlink.obj -MD -MP -MF $(DEPDIR)/readlink.Tpo -c -o readlink.obj `if test -f 'compat/readlink.c'; then $(CYGPATH_W) 'compat/readlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/readlink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/readlink.Tpo $(DEPDIR)/readlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/readlink.c' object='readlink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o readlink.obj `if test -f 'compat/readlink.c'; then $(CYGPATH_W) 'compat/readlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/readlink.c'; fi` + +symlink.o: compat/symlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT symlink.o -MD -MP -MF $(DEPDIR)/symlink.Tpo -c -o symlink.o `test -f 'compat/symlink.c' || echo '$(srcdir)/'`compat/symlink.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/symlink.Tpo $(DEPDIR)/symlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/symlink.c' object='symlink.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o symlink.o `test -f 'compat/symlink.c' || echo '$(srcdir)/'`compat/symlink.c + +symlink.obj: compat/symlink.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT symlink.obj -MD -MP -MF $(DEPDIR)/symlink.Tpo -c -o symlink.obj `if test -f 'compat/symlink.c'; then $(CYGPATH_W) 'compat/symlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/symlink.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/symlink.Tpo $(DEPDIR)/symlink.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/symlink.c' object='symlink.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o symlink.obj `if test -f 'compat/symlink.c'; then $(CYGPATH_W) 'compat/symlink.c'; else $(CYGPATH_W) '$(srcdir)/compat/symlink.c'; fi` + +sleep.o: compat/sleep.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sleep.o -MD -MP -MF $(DEPDIR)/sleep.Tpo -c -o sleep.o `test -f 'compat/sleep.c' || echo '$(srcdir)/'`compat/sleep.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sleep.Tpo $(DEPDIR)/sleep.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/sleep.c' object='sleep.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sleep.o `test -f 'compat/sleep.c' || echo '$(srcdir)/'`compat/sleep.c + +sleep.obj: compat/sleep.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sleep.obj -MD -MP -MF $(DEPDIR)/sleep.Tpo -c -o sleep.obj `if test -f 'compat/sleep.c'; then $(CYGPATH_W) 'compat/sleep.c'; else $(CYGPATH_W) '$(srcdir)/compat/sleep.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sleep.Tpo $(DEPDIR)/sleep.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/sleep.c' object='sleep.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sleep.obj `if test -f 'compat/sleep.c'; then $(CYGPATH_W) 'compat/sleep.c'; else $(CYGPATH_W) '$(srcdir)/compat/sleep.c'; fi` + +syslog.o: compat/syslog.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog.o -MD -MP -MF $(DEPDIR)/syslog.Tpo -c -o syslog.o `test -f 'compat/syslog.c' || echo '$(srcdir)/'`compat/syslog.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog.Tpo $(DEPDIR)/syslog.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/syslog.c' object='syslog.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog.o `test -f 'compat/syslog.c' || echo '$(srcdir)/'`compat/syslog.c + +syslog.obj: compat/syslog.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog.obj -MD -MP -MF $(DEPDIR)/syslog.Tpo -c -o syslog.obj `if test -f 'compat/syslog.c'; then $(CYGPATH_W) 'compat/syslog.c'; else $(CYGPATH_W) '$(srcdir)/compat/syslog.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog.Tpo $(DEPDIR)/syslog.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='compat/syslog.c' object='syslog.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog.obj `if test -f 'compat/syslog.c'; then $(CYGPATH_W) 'compat/syslog.c'; else $(CYGPATH_W) '$(srcdir)/compat/syslog.c'; fi` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ + distclean distclean-compile distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-binPROGRAMS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-binPROGRAMS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/bconsole.cpp b/src/bconsole.cpp new file mode 100644 index 0000000..c3a80a0 --- /dev/null +++ b/src/bconsole.cpp @@ -0,0 +1,176 @@ +/* bconsole.cpp + * + * Copyright (C) 2008-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#include "config.h" +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#else +#ifdef HAVE_WINSOCK_H +#include +#endif +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif + +#include "loghandler.h" +#include "mypopen.h" +#include "vconf.h" +#include "bconsole.h" + + +/* + * Function to issue command in Bacula console. + * Returns zero on success, or errno if there was an error running the command + * or a timeout occurred. + */ +int issue_bconsole_command(const char *bcmd) +{ + int pid, rc, n, len, fno_in = -1, fno_out = -1; + struct timeval tv; + fd_set rfd; + tString cmd, tmp; + char buf[4096]; + +#ifndef HAVE_WINDOWS_H + /* Build command line */ + cmd = conf.bconsole; + if (cmd.empty()) return 0; + if (!conf.bconsole_config.empty()) { + cmd += " -c "; + cmd += conf.bconsole_config; + } + cmd += " -n -u 30"; + /* Start bconsole process */ + log.Debug("bconsole: running '%s'", bcmd); + pid = mypopen_raw(cmd.c_str(), &fno_in, &fno_out, NULL); + if (pid < 0) { + rc = errno; + log.Error("bconsole: run failed errno=%d", rc); + errno = rc; + return rc; + } + /* Wait for bconsole to accept input */ + tv.tv_sec = 30; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(fno_in, &rfd); + rc = select(fno_in + 1, NULL, &rfd, NULL, &tv); + if (rc == 0) { + log.Error("bconsole: timed out waiting to send command"); + close(fno_in); + close(fno_out); + errno = ETIMEDOUT; + return ETIMEDOUT; + } + if (rc < 0) { + rc = errno; + log.Error("bconsole: errno=%d waiting to send command", rc); + close(fno_in); + close(fno_out); + errno = rc; + return rc; + } + /* Send command to bconsole's stdin */ + len = strlen(bcmd); + n = 0; + while (n < len) { + rc = write(fno_in, bcmd + n, len - n); + if (rc < 0) { + rc = errno; + log.Error("bconsole: send to bconsole's stdin failed errno=%d", rc); + close(fno_in); + close(fno_out); + errno = rc; + return rc; + } + n += rc; + } + close(fno_in); + + /* Read stdout from bconsole */ + memset(buf, 0, sizeof(buf)); + tmp.clear(); + while (true) { + tv.tv_sec = 30; + tv.tv_usec = 0; + FD_ZERO(&rfd); + FD_SET(fno_out, &rfd); + rc = select(fno_out + 1, &rfd, NULL, NULL, &tv); + if (rc == 0) { + log.Error("bconsole: timed out waiting for bconsole output"); + close(fno_out); + errno = ETIMEDOUT; + return ETIMEDOUT; + } + if (rc < 0) { + rc = errno; + log.Error("bconsole: errno=%d waiting for bconsole output", rc); + close(fno_out); + errno = rc; + return rc; + } + rc = read(fno_out, buf, 4095); + if (rc < 0) { + rc = errno; + log.Error("bconsole: errno=%d reading bconsole stdout", rc); + close(fno_out); + errno = rc; + return rc; + } else if (rc > 0) { + buf[rc] = 0; + tmp += buf; + } else break; + } + close(fno_out); + log.Debug("bconsole: output:\n%s", tmp.c_str()); + + /* Wait for bconsole process to finish */ + pid = waitpid(pid, &rc, 0); + if (!WIFEXITED(rc)) { + log.Error("bconsole: abnormal exit of bconsole process"); + return EPIPE; + } + if (WEXITSTATUS(rc)) { + log.Error("bconsole: exited with rc=%d", WEXITSTATUS(rc)); + return WEXITSTATUS(rc); + } + return 0; +#else + return EINVAL; +#endif +} diff --git a/src/bconsole.h b/src/bconsole.h new file mode 100644 index 0000000..adba63c --- /dev/null +++ b/src/bconsole.h @@ -0,0 +1,29 @@ +/* bconsole.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef BCONSOLE_H_ +#define BCONSOLE_H_ + +int issue_bconsole_command(const char *bcmd); + +#endif /* BCONSOLE_H_ */ diff --git a/src/changerstate.cpp b/src/changerstate.cpp new file mode 100644 index 0000000..9f6d923 --- /dev/null +++ b/src/changerstate.cpp @@ -0,0 +1,851 @@ +/* changerstate.cpp + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Provides a class to track state of virtual drives using files in + * the vchanger state directory. +*/ + +#include "config.h" +#include "compat_defs.h" +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDDEF_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "compat/getline.h" +#include "compat/readlink.h" +#include "compat/symlink.h" +#include "vconf.h" +#include "loghandler.h" +#include "errhandler.h" +#include "util.h" +#define __CHANGERSTATE_SOURCE 1 +#include "changerstate.h" +#include "uuidlookup.h" + +/////////////////////////////////////////////////// +// Class MagazineSlot +/////////////////////////////////////////////////// + +MagazineSlot::MagazineSlot(const MagazineSlot &b) +{ + mag_bay = b.mag_bay; + mag_slot = b.mag_slot; + label = b.label; +} + +MagazineSlot& MagazineSlot::operator=(const MagazineSlot &b) +{ + if (&b != this) { + mag_bay = b.mag_bay; + mag_slot = b.mag_slot; + label = b.label; + } + return *this; +} + +bool MagazineSlot::operator==(const MagazineSlot &b) +{ + if (&b == this) return true; + if (label == b.label) return true; + return false; +} + +bool MagazineSlot::operator!=(const MagazineSlot &b) +{ + if (&b == this) return false; + if (label != b.label) return true; + return false; +} + +/*------------------------------------------------- + * Method to clear object values + *-------------------------------------------------*/ +void MagazineSlot::clear() +{ + mag_bay = -1; + mag_slot = -1; + label.clear(); +} + + + +/////////////////////////////////////////////////// +// Class MagazineState +/////////////////////////////////////////////////// + +MagazineState::MagazineState(const MagazineState &b) +{ + mag_bay = b.mag_bay; + num_slots = b.num_slots; + start_slot = b.start_slot; + prev_num_slots = b.prev_num_slots; + prev_start_slot = b.prev_start_slot; + mag_dev = b.mag_dev; + mountpoint = b.mountpoint; + mslot = b.mslot; + verr = b.verr; +} + +MagazineState& MagazineState::operator=(const MagazineState &b) +{ + if (&b != this) { + mag_bay = b.mag_bay; + num_slots = b.num_slots; + start_slot = b.start_slot; + prev_num_slots = b.prev_num_slots; + prev_start_slot = b.prev_start_slot; + mag_dev = b.mag_dev; + mountpoint = b.mountpoint; + mslot = b.mslot; + verr = b.verr; + } + return *this; +} + +void MagazineState::clear() +{ + /* Notice that device and bay number are not cleared */ + num_slots = 0; + start_slot = 0; + mountpoint.clear(); + mslot.clear(); + verr.clear(); +} + +/*------------------------------------------------- + * Method to save current state of magazine bay to a file in + * the work directory named "bay" + bay_number. + * On success returns zero, otherwise sets lasterr and + * returns errno. + *-------------------------------------------------*/ +int MagazineState::save() +{ + mode_t old_mask; + int rc; + FILE *FS; + char sname[4096]; + + if (mag_bay < 0) { + verr.SetErrorWithErrno(EINVAL, "cannot save state of invalid magazine %d", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + /* Build path to state file */ + snprintf(sname, sizeof(sname), "%s%sbay_state-%d", conf.work_dir.c_str(), DIR_DELIM, mag_bay); + /* Remove magazine state files for unmounted magazines */ + if (mountpoint.empty() || mslot.empty()) { + unlink(sname); + return 0; + } + /* Write state file for mounted magazine */ + old_mask = umask(027); + FS = fopen(sname, "w"); + if (!FS) { + /* Unable to open state file for writing */ + rc = errno; + umask(old_mask); + verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for writing", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + /* Save magazine device (directory or UUID), number of volumes, and start of + * virtual slot range it is assigned */ + if (fprintf(FS, "%s,%d,%d\n", mag_dev.c_str(), num_slots, start_slot) < 0) { + /* I/O error writing state file */ + rc = errno; + fclose(FS); + unlink(sname); + umask(old_mask); + verr.SetErrorWithErrno(rc, "cannot write to magazine %d state file", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + fclose(FS); + umask(old_mask); + log.Notice("saved state of magazine %d", mag_bay); + return 0; +} + + +/*------------------------------------------------- + * Method to restore state of magazine from a file in the work + * directory named "bay_state-N", where N is the bay number. + * On success returns zero, otherwise sets lasterr and + * returns errno. + *-------------------------------------------------*/ +int MagazineState::restore() +{ + int rc; + tString line, word; + struct stat st; + FILE *FS; + size_t p; + char sname[4096]; + + if (mag_bay < 0) { + verr.SetErrorWithErrno(EINVAL, "cannot restore state of invalid magazine %d", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + clear(); + prev_num_slots = 0; + prev_start_slot = 0; + snprintf(sname, sizeof(sname), "%s%sbay_state-%d", conf.work_dir.c_str(), DIR_DELIM, mag_bay); + + /* Check for existing state file */ + if (stat(sname, &st)) { + /* magazine bay state file not found, so bay did not previously + * contain a magazine */ + return 0; + } + /* Read bay state file */ + FS = fopen(sname, "r"); + if (!FS) { + /* No read permission? */ + rc = errno; + verr.SetErrorWithErrno(rc, "cannot open magazine %d state file for reading", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + if (tGetLine(line, FS) == NULL) { + rc = errno; + if (!feof(FS)) { + /* error reading bay state file */ + fclose(FS); + verr.SetErrorWithErrno(rc, "error reading magazine %d state file", mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + } + fclose(FS); + + /* Get magazine device (UUID or path specified in config) */ + tStrip(tRemoveEOL(line)); + p = 0; + if (tParseCSV(word, line, p) <= 0) { + /* bay state file should not be empty, assume it didn't exist */ + log.Warning("WARNING! magazine %d state file was empty, deleting it", mag_bay); + unlink(sname); + return 0; + } + if (mag_dev != word) { + /* Order of mag bays has changed in config file so ignore old state */ + unlink(sname); + return 0; + } + + /* Get number of slots */ + if (tParseCSV(word, line, p) <= 0) { + /* Bay state file is corrupt. + * Treat as if it was not mounted at last invocation */ + clear(); + log.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay); + unlink(sname); + return 0; + } + if (!isdigit(word[0])) { + /* Corrupt bay state file, assume it doesn't exist */ + clear(); + unlink(sname); + log.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay); + return 0; + } + prev_num_slots = (int)strtol(word.c_str(), NULL, 10); + if (prev_num_slots < 0) { + /* Corrupt bay state file, assume it doesn't exist */ + clear(); + prev_num_slots = 0; + unlink(sname); + log.Warning("WARNING! magazine %d state file has invalid number of slots field, deleting it", mag_bay); + return 0; + } + + /* Get virtual slot number offset */ + if (tParseCSV(word, line, p) <= 0) { + /* Bay state file is corrupt. + * Treat as if it was not mounted at last invocation */ + clear(); + prev_num_slots = 0; + log.Warning("WARNING! magazine %d state file corrupt, deleting it", mag_bay); + unlink(sname); + return 0; + } + if (!isdigit(word[0])) { + /* Corrupt bay state file, assume it doesn't exist */ + clear(); + prev_num_slots = 0; + unlink(sname); + log.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it", + mag_bay); + return 0; + } + prev_start_slot = (int)strtol(word.c_str(), NULL, 10); + if (prev_start_slot <= 0) { + /* Corrupt bay state file, assume it doesn't exist */ + clear(); + prev_num_slots = 0; + prev_start_slot = 0; + unlink(sname); + log.Warning("WARNING! magazine %d state file has invalid virtual slot assignment field, deleting it", + mag_bay); + return 0; + } + log.Notice("restored state of magazine %d", mag_bay); + return 0; +} + + +/*------------------------------------------------- + * Method to update a magazine from vchanger version 0.x format + * to the format used with version 1.0.0 or higher. + * Return values are: + * 0 Success + *-------------------------------------------------*/ +int MagazineState::UpdateMagazineFormat() +{ + FILE *fs; + DIR *dir; + struct dirent *de; + struct stat st; + tString str, fname, lname, vname; + int drv; + + /* Rename driveN files to their volume file name */ + dir = opendir(mountpoint.c_str()); + if (!dir) return -1; + de = readdir(dir); + while (de) { + /* Skip if not regular file */ + tFormat(fname, "%s%s%s", mountpoint.c_str(), DIR_DELIM, de->d_name); + stat(fname.c_str(), &st); + if (!S_ISREG(st.st_mode)) { + de = readdir(dir); + continue; + } + /* Skip index file */ + if (tCaseCmp(de->d_name, "index") == 0) { + de = readdir(dir); + continue; + } + str = de->d_name; + if (str.find("drive") == 0) { + str.erase(0, 5); + if (str.find_first_of("0123456789") == tString::npos) { + de = readdir(dir); + continue; + } + if (str.find_first_not_of("0123456789") != tString::npos) { + de = readdir(dir); + continue; + } + drv = (int)strtol(str.c_str(), NULL, 10); + tFormat(lname, "%s%sloaded%d", mountpoint.c_str(), DIR_DELIM, drv); + fs = fopen(lname.c_str(), "r"); + if (fs == NULL) { + verr.SetErrorWithErrno(errno, "failed to find loaded%d file when updating magazine %d", drv, mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + de = readdir(dir); + continue; + } + tGetLine(str, fs); + fclose(fs); + if (str.empty()) { + verr.SetError(-1, "loaded%d file empty when updating magazine %d", drv, mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + de = readdir(dir); + continue; + } + tStrip(tRemoveEOL(str)); + tFormat(vname, "%s%s%s", mountpoint.c_str(), DIR_DELIM, str.c_str()); + if (rename(fname.c_str(), vname.c_str())) { + verr.SetError(EINVAL, "unable to rename 'drive%d' on magazine %d", + drv, mag_bay); + log.Error("ERROR! %s", verr.GetErrorMsg()); + } + } + de = readdir(dir); + } + closedir(dir); + + /* Delete loadedN files */ + dir = opendir(mountpoint.c_str()); + de = readdir(dir); + while (de) { + str = de->d_name; + /* Skip if not regular file */ + tFormat(fname, "%s%s%s", mountpoint.c_str(), DIR_DELIM, de->d_name); + stat(fname.c_str(), &st); + if (!S_ISREG(st.st_mode)) { + de = readdir(dir); + continue; + } + if (str.find("loaded") == 0) { + str.erase(0, 6); + if (str.find_first_of("0123456789") == tString::npos) { + de = readdir(dir); + continue; + } + if (str.find_first_not_of("0123456789") != tString::npos) { + de = readdir(dir); + continue; + } + unlink(fname.c_str()); + } + de = readdir(dir); + } + closedir(dir); + + /* Delete index file */ + tFormat(fname, "%s%sindex", mountpoint.c_str(), DIR_DELIM); + unlink(fname.c_str()); + + log.Warning("magaine %d updated from old format", mag_bay); + return 0; +} + + +/*------------------------------------------------- + * Method to determine mountpoint of magazine and assign its volume files + * to magazine slots. Regular files on the magazine are assigned slots in + * ascending alphanumeric order by filename beginning with magazine slot zero. + * If the magazine's device string begins with "UUID:" (case insensitive), + * then it specifies the UUID of a file system on a disk partition to be used + * as the virtual magazine. Otherwise, it specifies a directory to be used as + * the virtual magazine. If a UUID is given, then the system is queried to + * determine the mountpoint of the filesystem with the given UUID. The magazine + * device must already be mounted or configured to be auto-mounted. + * Return values are: + * 0 Magazine assigned successfully + * -1 system error + * -2 parameter error + * -3 magname not found or not mounted + * -5 permission denied + *-------------------------------------------------*/ +int MagazineState::Mount() +{ + int rc, s; + DIR *dir; + struct dirent *de; + struct stat st; + tString fname, line, path; + MagazineSlot v; + std::list vname; + std::list::iterator p; + char buf[4096]; + + clear(); + if (tCaseFind(mag_dev, "uuid:") != 0) { + /* magazine specified as filesystem path */ + mountpoint = mag_dev; + } else { + /* magazine specified as UUID, so query OS for mountpoint */ + rc = GetMountpointFromUUID(buf, sizeof(buf), mag_dev.substr(5).c_str()); + mountpoint = buf; + if (rc == -3 || rc == -4) { + /* magazine device not found or not mounted */ + mountpoint.clear(); + return -3; + } + if (rc) { + verr.SetError(rc, "system error determining mountpoint from UUID"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + mountpoint.clear(); + return -1; + } + } + + /* Check mountpoint exists */ + if (access(mountpoint.c_str(), F_OK) != 0) { + /* Mountpoint not found */ + mountpoint.clear(); + return -3; + } + + /* Ensure access to magazine mountpoint */ + if (access(mountpoint.c_str(), W_OK) != 0) { + verr.SetError(rc, "no write access to directory %s", mountpoint.c_str()); + log.Error("%s", verr.GetErrorMsg()); + mountpoint.clear(); + return -5; + } + + /* If this magazine contains a file named index then assume it was + * created by an old version of vchanger and prepare it for use + * by removing meta-information files. */ + tFormat(fname, "%s%sindex", mountpoint.c_str(), DIR_DELIM); + if (access(fname.c_str(), F_OK) == 0) { + UpdateMagazineFormat(); + } + + /* Build list of this magazine's volume files */ + dir = opendir(mountpoint.c_str()); + if (!dir) { + /* could not open mountpoint dir */ + rc = errno; + verr.SetErrorWithErrno(rc, "cannot open directory '%s'", mountpoint.c_str()); + log.Error("ERROR! %s", verr.GetErrorMsg()); + mountpoint.clear(); + if (rc == ENOTDIR || rc == ENOENT) return -3; + if (rc == EACCES) return -5; + return -1; + } + de = readdir(dir); + while (de) { + /* Skip if not regular file */ + tFormat(path, "%s%s%s", mountpoint.c_str(), DIR_DELIM, de->d_name); + stat(path.c_str(), &st); + if (!S_ISREG(st.st_mode)) { + de = readdir(dir); + continue; + } + /* Writable regular files on magazine are considered volume files */ + if (access(path.c_str(), W_OK) == 0) { + vname.push_back(de->d_name); + } + de = readdir(dir); + } + closedir(dir); + if (vname.empty()) { + /* Magazine is ready for use but has no volumes */ + start_slot = 0; + num_slots = 0; + return 0; + } + /* Assign volume files to slots in alphanumeric order */ + vname.sort(); + s = 0; + for (p = vname.begin(); p != vname.end(); p++) { + v.mag_bay = mag_bay; + v.label = *p; + v.mag_slot = s++; + mslot.push_back(v); + } + num_slots = (int)mslot.size(); + return 0; +} + + +/*------------------------------------------------- + * Method to get path to volume file in a magazine slot + * On success returns path, else returns empty string + *-------------------------------------------------*/ +const char* MagazineState::GetVolumeLabel(int ms) const +{ + if (ms >= 0 && ms < (int)mslot.size() && !mslot[ms].empty()) { + return mslot[ms].label.c_str(); + } + return ""; +} + + +/*------------------------------------------------- + * Method to get path to volume file in a magazine slot + * On success returns path, else returns empty string + *-------------------------------------------------*/ +tString MagazineState::GetVolumePath(int ms) +{ + tString result; + if (ms >= 0 && ms < (int)mslot.size()) { + tFormat(result, "%s%s%s", mountpoint.c_str(), DIR_DELIM, GetVolumeLabel(ms)); + } + return result; +} + + +/*------------------------------------------------- + * Method to get path to volume file in a magazine slot + * On success returns path, else returns empty string + *-------------------------------------------------*/ +const char* MagazineState::GetVolumePath(tString &path, int ms) +{ + path = GetVolumePath(ms); + return path.c_str(); +} + + +/*------------------------------------------------- + * Method to get magazine slot containing a label. + * On success returns magazine slot number, else negative. + *-------------------------------------------------*/ +int MagazineState::GetVolumeSlot(const char *label) +{ + int n; + for (n = 0; n < num_slots; n++) { + if (mslot[n].label == label) return n; + } + return -1; +} + + +/*------------------------------------------------- + * Method to create a new volume file. 'vol_label_in' gives the + * name of the new volume file to create on the magazine. If empty, + * then a volume file name is generated based on the magazine's name. + * A new magazine slot is appended to hold the new volume and a new + * virtual slot is appended that maps to the new magazine slot. + * On success returns zero, else sets lasterr and returns negative + *-------------------------------------------------*/ +int MagazineState::CreateVolume(const char *vol_label_in) +{ + int rc = 0, slot; + FILE *fs; + tString fname, label(vol_label_in); + MagazineSlot new_mslot; + + if (label.empty()) { + slot = (int)mslot.size(); + --slot; + while(rc == 0) { + ++slot; + tFormat(label, "%s_%d_%d", conf.storage_name.c_str(), mag_bay, slot); + tFormat(fname, "%s%s%s", mountpoint.c_str(), DIR_DELIM, label.c_str()); + if (access(fname.c_str(), F_OK)) rc = errno; + else rc = 0; + } + } else { + tFormat(fname, "%s%s%s", mountpoint.c_str(), DIR_DELIM, label.c_str()); + if (access(fname.c_str(), F_OK)) rc = errno; + else rc = 0; + if (rc == 0) { + verr.SetErrorWithErrno(rc, "volume %s already exists on magazine %d", label.c_str(), mag_bay); + return EEXIST; + } + } + if (rc != ENOENT) { + verr.SetErrorWithErrno(rc, "error %d accessing volumes on magazine %d", rc, mag_bay); + log.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg()); + return -1; + } + /* Create new volume file on magazine */ + fs = fopen(fname.c_str(), "w"); + if (!fs) { + rc = errno; + verr.SetErrorWithErrno(rc, "error %d creating volume on magazine %d", rc, mag_bay); + log.Error("MagazineState::CreateVolume: %s", verr.GetErrorMsg()); + return -1; + } + fclose(fs); + new_mslot.mag_bay = mag_bay; + new_mslot.mag_slot = mslot.size(); + new_mslot.label = label; + mslot.push_back(new_mslot); + ++num_slots; + log.Notice("created volume '%s' on magazine %d (%s)", label.c_str(), mag_bay, mag_dev.c_str()); + return 0; +} + + +/*------------------------------------------------- + * Method to assign bay number and device for this magazine + *-------------------------------------------------*/ +void MagazineState::SetBay(int bay, const char *dev) +{ + mag_bay = bay; + mag_dev = dev; + clear(); +} + + + +/////////////////////////////////////////////////// +// Class VirtualSlot +/////////////////////////////////////////////////// + +VirtualSlot::VirtualSlot(const VirtualSlot &b) +{ + vs = b.vs; + drv = b.drv; + mag_bay = b.mag_bay; + mag_slot = b.mag_slot; +} + +VirtualSlot& VirtualSlot::operator=(const VirtualSlot &b) +{ + if (this != &b) { + vs = b.vs; + drv = b.drv; + mag_bay = b.mag_bay; + mag_slot = b.mag_slot; + } + return *this; +} + + +/*------------------------------------------------- + * Method to clear an virtual slot's values + *-------------------------------------------------*/ +void VirtualSlot::clear() +{ + drv = -1; + mag_bay = -1; + mag_slot = -1; +} + + + +/////////////////////////////////////////////////// +// Class DriveState +/////////////////////////////////////////////////// + +DriveState::DriveState(const DriveState &b) +{ + drv = b.drv; + vs = b.vs; +} + +DriveState& DriveState::operator=(const DriveState &b) +{ + if (&b != this) { + drv = b.drv; + vs = b.vs; + } + return *this; +} + +/* + * Method to clear a drive's values + */ +void DriveState::clear() +{ + /* do not clear drive number */ + vs = -1; +} + + + +/////////////////////////////////////////////////// +// Class DynamicConfig +/////////////////////////////////////////////////// + +/*------------------------------------------------- + * Method to save dynamic configuration info to a file in + * the work directory named dynamic.conf. + *-------------------------------------------------*/ +void DynamicConfig::save() +{ + mode_t old_mask; + int rc; + FILE *FS; + char sname[4096]; + + if (max_slot < 10) max_slot = 10; + /* Build path to dynamic.conf file */ + snprintf(sname, sizeof(sname), "%s%sdynamic.conf", conf.work_dir.c_str(), DIR_DELIM); + /* Write dynamic config info */ + old_mask = umask(027); + FS = fopen(sname, "w"); + if (!FS) { + /* Unable to open dynamic.conf file for writing */ + rc = errno; + umask(old_mask); + log.Error("ERROR! cannot open dynamic.conf file for writing (errno=%d)", rc); + return; + } + /* Save max slot number in use to dynamic configuration */ + if (fprintf(FS, "max_used_slot=%d\n", max_slot) < 0) { + /* I/O error writing dynamic.conf file */ + rc = errno; + fclose(FS); + unlink(sname); + umask(old_mask); + log.Error("ERROR! i/o error writing dynamic.conf file (errno=%d)", rc); + return; + } + fclose(FS); + umask(old_mask); + log.Notice("saved dynamic configuration (max used slot: %d)", max_slot); +} + + +/*------------------------------------------------- + * Method to restore dynamic configuration info. + *-------------------------------------------------*/ +void DynamicConfig::restore() +{ + int rc; + tString line; + struct stat st; + FILE *FS; + char sname[4096]; + + if (max_slot < 10) max_slot = 10; + /* Build path to dynamic.conf file */ + snprintf(sname, sizeof(sname), "%s%sdynamic.conf", conf.work_dir.c_str(), DIR_DELIM); + /* Check for existing file */ + if (stat(sname, &st)) { + /* dynamic configuration file not found */ + return; + } + /* Read dynamic.conf file */ + FS = fopen(sname, "r"); + if (!FS) { + /* No read permission? */ + rc = errno; + log.Error("ERROR! cannot open dynamic.conf file for restore (errno=%d)", rc); + return; + } + if (tGetLine(line, FS) == NULL) { + rc = errno; + if (!feof(FS)) { + /* error reading bay state file */ + fclose(FS); + log.Error("ERROR! i/o error reading dynamic.conf file (errno=%d)", rc); + return; + } + } + fclose(FS); + + /* Get magazine device (UUID or path specified in config) */ + tStrip(tRemoveEOL(line)); + if (tCaseFind(line, "max_used_slot") == 0) { + max_slot = (int)strtol(line.substr(14).c_str(), NULL, 10); + if (max_slot < 10) max_slot = 10; + } +} + diff --git a/src/changerstate.h b/src/changerstate.h new file mode 100644 index 0000000..1ff4e83 --- /dev/null +++ b/src/changerstate.h @@ -0,0 +1,137 @@ +/* changerstate.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ +#ifndef CHANGERSTATE_H_ +#define CHANGERSTATE_H_ + +#include +#include "tstring.h" +#include "errhandler.h" + +class MagazineSlot +{ +public: + MagazineSlot() : mag_bay(-1), mag_slot(-1) {} + MagazineSlot(const MagazineSlot &b); + virtual ~MagazineSlot() {} + MagazineSlot& operator=(const MagazineSlot &b); + bool operator==(const MagazineSlot &b); + bool operator!=(const MagazineSlot &b); + void clear(); + inline bool empty() { return label.empty(); } + inline bool empty() const { return label.empty(); } + inline bool operator==(const char *lab) { return (label == lab); } + inline bool operator!=(const char *lab) { return (label != lab); } +public: + int mag_bay; + int mag_slot; + tString label; +}; + +typedef std::vector MagazineSlotArray; + +class MagazineState +{ +public: + MagazineState() : mag_bay(-1), num_slots(0), start_slot(0), prev_num_slots(0), prev_start_slot(0) {} + MagazineState(const MagazineState &b); + virtual ~MagazineState() {} + MagazineState& operator=(const MagazineState &b); + void clear(); + int save(); + int restore(); + int Mount(); + void SetBay(int bay, const char *dev); + inline void SetBay(int bay, const tString &dev) { SetBay(bay, dev.c_str()); } + tString GetVolumePath(int mag_slot); + const char* GetVolumePath(tString &path, int slot); + const char* GetVolumeLabel(int mag_slot) const; + int GetVolumeSlot(const char *fname); + inline int GetVolumeSlot(const tString &fname) { return GetVolumeSlot(fname.c_str()); } + int CreateVolume(const char *vol_label = ""); + inline int CreateVolume(const tString &labl) { return CreateVolume(labl.c_str()); } + inline bool empty() { return mountpoint.empty(); } + inline bool empty() const { return mountpoint.empty(); } +protected: + int ReadMagazineIndex(); + int UpdateMagazineFormat(); +public: + int mag_bay; + int num_slots; + int start_slot; + int prev_num_slots; + int prev_start_slot; + tString mag_dev; + tString mountpoint; + MagazineSlotArray mslot; + ErrorHandler verr; +}; + +typedef std::vector MagazineStateArray; + +class VirtualSlot +{ +public: + VirtualSlot() : vs(0), drv(-1), mag_bay(-1), mag_slot(-1) {} + VirtualSlot(const VirtualSlot &b); + virtual ~VirtualSlot() {} + VirtualSlot& operator=(const VirtualSlot &b); + void clear(); + bool empty() { return mag_bay < 0; } + bool empty() const { return mag_bay < 0; } +public: + int vs; + int drv; + int mag_bay; + int mag_slot; +}; + +typedef std::vector VirtualSlotArray; + +class DynamicConfig +{ +public: + DynamicConfig() : max_slot(0) {} + void save(); + void restore(); +public: + int max_slot; +}; + +class DriveState +{ +public: + DriveState() : drv(-1), vs(-1) {} + DriveState(const DriveState &b); + virtual ~DriveState() {} + DriveState& operator=(const DriveState &b); + void clear(); + inline bool empty() { return vs < 0; } + inline bool empty() const { return vs < 0; } +public: + int drv; + int vs; +}; + +typedef std::vector DriveStateArray; + +#endif /*CHANGERSTATE_H_*/ diff --git a/src/compat/getline.c b/src/compat/getline.c new file mode 100644 index 0000000..e8d6892 --- /dev/null +++ b/src/compat/getline.c @@ -0,0 +1,81 @@ +/* getline.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_GETLINE + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include "compat/getline.h" + +/* + * Emulate GNU extension function getline(). + */ +ssize_t getline(char **lineptr, size_t *lineptr_sz, FILE *stream) +{ + int c; + size_t n = 0; + + c = fgetc(stream); + if (c == EOF) { + return -1; + } + if (*lineptr == NULL) { + *lineptr_sz = 4096; + *lineptr = (char*)malloc(*lineptr_sz); + if (*lineptr == NULL) { + return -1; + } + } + while (c != EOF && c != '\n') + { + if (n + 1 >= *lineptr_sz) { + *lineptr_sz += 4096; + *lineptr = (char*)realloc(*lineptr, *lineptr_sz); + if (*lineptr == NULL) { + return -1; + } + } + (*lineptr)[n++] = (char)c; + c = fgetc(stream); + } + if (c == '\n') { + if (n && (*lineptr)[n-1] == '\r') { + (*lineptr)[n-1] = '\n'; + } else { + (*lineptr)[n++] = '\n'; + } + } + (*lineptr)[n] = 0; + return (ssize_t)n; +} +#endif diff --git a/src/compat/getline.h b/src/compat/getline.h new file mode 100644 index 0000000..2f43869 --- /dev/null +++ b/src/compat/getline.h @@ -0,0 +1,38 @@ +/* getline.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _GETLINE_H_ +#define _GETLINE_H_ + +#ifndef HAVE_GETLINE +/* For systems without getline function, use internal version */ +#ifdef __cplusplus +extern "C" { +#endif +ssize_t getline(char **lineptr, size_t *n, FILE *stream); +#ifdef __cplusplus +} +#endif +#endif + +#endif /* _GETLINE_H */ diff --git a/src/compat/gettimeofday.c b/src/compat/gettimeofday.c new file mode 100644 index 0000000..2b5983d --- /dev/null +++ b/src/compat/gettimeofday.c @@ -0,0 +1,118 @@ +/* gettimeofday.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_GETTIMEOFDAY + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#include +#endif +#ifdef HAV_SYS_TYPES_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include "compat/gettimeofday.h" + + +#ifndef HAVE_WINDOWS_H +/* + * Emulate POSIX.1-2001 gettimeofday() function using the time() function. + */ +int gettimeofday(struct timeval *tv, struct timezone* tz) +{ + if (tv != NULL) { + tv->tv_sec = time(NULL); + tv->tv_usec = 0; + } + if (tz != NULL) { + if (!tzflag) { + tzset(); + tzflag++; + } + // Adjust for the timezone west of Greenwich + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + return 0; +} + +#else + +/* + * Emulate POSIX.1-2001 gettimeofday() function using the win32 + * GetSystemTimeAsFIleTime() system function. +*/ +int gettimeofday(struct timeval *tv, struct timezone* tz) +{ + FILETIME ft; + int64_t tmpres = 0; + static int tzflag = 0; + + if (tv != NULL) { + GetSystemTimeAsFileTime(&ft); + + /* The GetSystemTimeAsFileTime returns the number of 100 nanosecond + * intervals since Jan 1, 1601 in a structure. Copy the high bits to + * the 64 bit tmpres, shift it left by 32 then or in the low 32 bits. + */ + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /* Convert to microseconds by dividing by 10 */ + tmpres /= 10; + + /* The Unix epoch starts on Jan 1 1970. Need to subtract the difference + * in seconds from Jan 1 1601. + */ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + + /* Finally change microseconds to seconds and place in the seconds value. + * The modulus picks up the microseconds. + */ + tv->tv_sec = tmpres / 1000000L; + tv->tv_usec = (tmpres % 1000000L); + } + + if (NULL != tz) { + if (!tzflag) { + _tzset(); + tzflag++; + } + // Adjust for the timezone west of Greenwich + tz->tz_minuteswest = _timezone / 60; + tz->tz_dsttime = _daylight; + } + + return 0; +} +#endif + +#endif diff --git a/src/compat/gettimeofday.h b/src/compat/gettimeofday.h new file mode 100644 index 0000000..6a67a16 --- /dev/null +++ b/src/compat/gettimeofday.h @@ -0,0 +1,62 @@ +/* gettimeofday.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _GETTIMEOFDAY_H +#define _GETTIMEOFDAY_H + +#ifndef HAVE_GETTIMEOFDAY +/* For systems without gettimeofday function, use internal version */ + +#ifdef HAVE_WINDOWS_H +#define EPOCH_FILETIME (116444736000000000LL) // 100 ns intervals between FILETIME epoch and Unix epoch +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +#define suseconds_t long +struct timeval +{ + time_t tv_sec; + suseconds_t tv_usec; +}; + +struct timezone +{ + int tz_minuteswest; + int tz_dsttime; +}; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +int gettimeofday(struct timeval *tv, struct timezone *tz); +#ifdef __cplusplus +} +#endif +#endif + + +#endif /* _GETTIMEOFDAY_H */ diff --git a/src/compat/getuid.c b/src/compat/getuid.c new file mode 100644 index 0000000..1ebb6bf --- /dev/null +++ b/src/compat/getuid.c @@ -0,0 +1,46 @@ +/* getuid.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_GETUID + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include "compat/getuid.h" + +/* + * Emulate GNU extension function getline(). + */ +uid_t getuid() +{ + return 999; +} + +gid_t getgid() +{ + return 999; +} + +#endif diff --git a/src/compat/getuid.h b/src/compat/getuid.h new file mode 100644 index 0000000..1d5fb95 --- /dev/null +++ b/src/compat/getuid.h @@ -0,0 +1,45 @@ +/* getuid.h +* +* This file is part of vchanger by Josh Fisher. +* +* vchanger copyright (C) 2008-2014 Josh Fisher +* +* vchanger is free software. +* You may redistribute it and/or modify it under the terms of the +* GNU General Public License version 2, as published by the Free +* Software Foundation. +* +* vchanger 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 vchanger. See the file "COPYING". If not, +* write to: The Free Software Foundation, Inc., +* 59 Temple Place - Suite 330, +* Boston, MA 02111-1307, USA. +*/ + +#ifndef _GETUID_H_ +#define _GETUID_H_ + +#ifndef HAVE_GETUID +/* For systems without getuid function, use internal version */ + +#ifdef HAVE_WINDOWS_H +typedef unsigned int uid_t; +typedef unsigned int gid_t; +#endif + +#ifdef __cplusplus +extern "C" { +#endif +uid_t getuid(); +gid_t getgid(); +#ifdef __cplusplus +} +#endif +#endif + +#endif /* _GETUID_H */ diff --git a/src/compat/localtime_r.c b/src/compat/localtime_r.c new file mode 100644 index 0000000..42ac402 --- /dev/null +++ b/src/compat/localtime_r.c @@ -0,0 +1,57 @@ +/* + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_LOCALTIME_R + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include "compat/localtime_r.h" + +/* + * Emulate SUSv2 localtime_r() function using C89 localtime(). On Win32 + * localtime() is thread safe. For all others, note that this keeps the + * caller from using the unsafe buffer over any extended period, + * but it is still not thread safe and will fail if two threads call this + * function nearly simultaneously. + */ +struct tm* localtime_r(const time_t *timep, struct tm *buf) +{ + struct tm *tm1 = localtime(timep); + if (!tm1) return NULL; + memcpy(buf, tm1, sizeof(struct tm)); + return buf; +} + +#endif diff --git a/src/compat/localtime_r.h b/src/compat/localtime_r.h new file mode 100644 index 0000000..113e470 --- /dev/null +++ b/src/compat/localtime_r.h @@ -0,0 +1,39 @@ +/* + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _LOCALTIME_R_H_ +#define _LOCALTIME_R_H_ + +#ifndef HAVE_LOCALTIME_R +/* For systems without localtime_r function, use internal version */ +#ifdef __cplusplus +extern "C" { +#endif +struct tm* localtime_r(const time_t *timep, struct tm *buf); +#ifdef __cplusplus +} +#endif +#endif + + +#endif /* _LOCALTIME_R_H_ */ diff --git a/src/compat/readlink.c b/src/compat/readlink.c new file mode 100644 index 0000000..51c4d48 --- /dev/null +++ b/src/compat/readlink.c @@ -0,0 +1,126 @@ +/* readlink.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_READLINK + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STDDEF_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#include "win32_util.h" +#include "compat/readlink.h" + +#ifdef HAVE_WINDOWS_H + +/*------------------------------------------------- + * Emulate POSIX.1-2001 readlink() function using win32/win64 CreateFileW() + * and GetFinalPathNameByHandleW() functions. + * On success returns the length of the target path string. On + * error returns -1 and sets errno. + *-------------------------------------------------*/ +ssize_t readlink(const char *path_in, char *buf, size_t bufsiz) +{ + HANDLE hFS; + DWORD dw; + wchar_t *p16, *path = NULL; + size_t path_sz = 0; + + /* Convert path string to UTF16 encoding */ + if (!AnsiToUTF16(path_in, &path, &path_sz)) { + errno = w32errno(ERROR_BAD_PATHNAME); + return -1; + } + /* Check attributes of path to see if it is a symlink */ + dw = GetFileAttributesW(path); + if (dw == INVALID_FILE_ATTRIBUTES) { + /* Error getting attributes */ + errno = w32errno(GetLastError()); + free(path); + return -1; + } + if ((dw & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + /* path does not point to a symlink */ + errno = EINVAL; + return -1; + } + /* Get an open handle to the symlink's target file */ + hFS = CreateFileW(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFS == INVALID_HANDLE_VALUE) { + /* Failed to open file */ + errno = w32errno(GetLastError()); + free(path); + return -1; + } + /* Get the full final UTF-16 path name of the opened file */ + free(path); + path = (wchar_t*)malloc(65536); + dw = GetFinalPathNameByHandleW(hFS, path, 32768, FILE_NAME_OPENED); + if (dw == 0) { + /* Failed to get final path */ + errno = w32errno(GetLastError()); + CloseHandle(hFS); + free(path); + return -1; + } + /* Close file handle and get pointer to UTF-16 target path */ + CloseHandle(hFS); + p16 = path; + if (path[0] == L'\\' && path[2] == L'?' && path[3] == L'\\') { + p16 = path + 4; + dw -= 4; + } + if (dw > bufsiz) { + /* Caller's buffer too small */ + errno = EINVAL; + free(path); + return -1; + } + /* Convert target path to ANSI in caller's buffer */ + if (!UTF16ToAnsi(p16, &buf, &bufsiz)) { + /* Failed to convert to ANSI */ + errno = EINVAL; + free(path); + return -1; + } + free(path); + return strlen(buf); + } + +#endif + +#endif diff --git a/src/compat/readlink.h b/src/compat/readlink.h new file mode 100644 index 0000000..d178f21 --- /dev/null +++ b/src/compat/readlink.h @@ -0,0 +1,42 @@ +/* readlink.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _READLINK_H +#define _READLINK_H + +#ifndef HAVE_READLINK +/* For systems without readlink function, use internal version */ + +#ifdef __cplusplus +extern "C" { +#endif + +ssize_t readlink(const char *path, char *buf, size_t bufsiz); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* _READLINK_H */ diff --git a/src/compat/sleep.c b/src/compat/sleep.c new file mode 100644 index 0000000..ec55202 --- /dev/null +++ b/src/compat/sleep.c @@ -0,0 +1,39 @@ +/* sleep.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#include "windows.h" + +/* + * Emulate GNU extension function getline(). + */ +unsigned int sleep(unsigned int seconds) +{ + Sleep(seconds * 1000); + return 0; +} + +#endif diff --git a/src/compat/sleep.h b/src/compat/sleep.h new file mode 100644 index 0000000..6031a44 --- /dev/null +++ b/src/compat/sleep.h @@ -0,0 +1,42 @@ +/* sleep.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _SLEEP_H +#define _SLEEP_H + +#ifdef HAVE_WINDOWS_H +/* For Windows provide sleep() function using Win32 API Sleep() */ + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned int sleep(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* _SLEEP_H */ diff --git a/src/compat/symlink.c b/src/compat/symlink.c new file mode 100644 index 0000000..45e2245 --- /dev/null +++ b/src/compat/symlink.c @@ -0,0 +1,87 @@ +/* symlink.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_SYMLINK + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#include +#include "win32_util.h" +#endif +/* +#ifdef HAVE_ERRNO_H +#include +#endif +*/ +#include "compat/symlink.h" + +#ifdef HAVE_WINDOWS_H + +/*------------------------------------------------- + * Emulate POSIX.1-2001 symlink() function using win32/win64 CreateSymbolicLinkW() function. + * On success returns zero, else negative on error. + *-------------------------------------------------*/ +int symlink(const char *oldpath, const char *newpath) +{ + DWORD rc, attr, dwFlags; + wchar_t *woldpath = NULL, *wnewpath = NULL; + size_t woldpath_sz = 0, wnewpath_sz = 0; + + /* Convert path strings to UTF16 encoding */ + if (!AnsiToUTF16(oldpath, &woldpath, &woldpath_sz)) { + rc = ERROR_BAD_PATHNAME; + errno = w32errno(rc); + return -1; + } + if (!AnsiToUTF16(newpath, &wnewpath, &wnewpath_sz)) { + rc = ERROR_BAD_PATHNAME; + errno = w32errno(rc); + free(woldpath); + return -1; + } + /* Determine if oldpath is a file or directory */ + attr = GetFileAttributesW(woldpath); + if (attr == INVALID_FILE_ATTRIBUTES) { + free(woldpath); + free(wnewpath); + errno = w32errno(GetLastError()); + return -1; + } + dwFlags = (attr & FILE_ATTRIBUTE_DIRECTORY) == 0 ? 0 : 1; + /* Create the symlink */ + if (CreateSymbolicLinkW(wnewpath, woldpath, dwFlags)) { + free(woldpath); + free(wnewpath); + return 0; + } + free(woldpath); + free(wnewpath); + errno = w32errno(GetLastError()); + return -1; +} + +#endif + +#endif diff --git a/src/compat/symlink.h b/src/compat/symlink.h new file mode 100644 index 0000000..b000a96 --- /dev/null +++ b/src/compat/symlink.h @@ -0,0 +1,42 @@ +/* symlink.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _SYMLINK_H +#define _SYMLINK_H + +#ifndef HAVE_SYMLINK +/* For systems without symlink() function, use internal version */ + +#ifdef __cplusplus +extern "C" { +#endif + +int symlink(const char *oldpath, const char *newpath); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif /* _SYMLINK_H */ diff --git a/src/compat/syslog.c b/src/compat/syslog.c new file mode 100644 index 0000000..71c29a0 --- /dev/null +++ b/src/compat/syslog.c @@ -0,0 +1,57 @@ +/* compat_syslog.c + * + * This file is part of vchanger by Josh Fisher. + * + * Provide syslog() replacement function for non-POSIX systems. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifndef HAVE_SYSLOG + +#ifdef HAVE_STDARG_H +#include +#endif +#include "compat/syslog.h" + +#ifdef HAVE_WINDOWS_H +/* Windows doesn't do syslog() ... ignore for now. Perhaps win32 event logging + * could be used to emulate syslog in future. + */ +void openlog(const char *app, int option, int facility) +{ +} + +void closelog(void) +{ +} + +void syslog(int type, const char *fmt, ...) +{ +} + +void vsyslog(int type, const char *fmt, va_list ap) +{ +} + +#endif + +#endif diff --git a/src/compat/syslog.h b/src/compat/syslog.h new file mode 100644 index 0000000..0632b80 --- /dev/null +++ b/src/compat/syslog.h @@ -0,0 +1,80 @@ +/* compat_syslog.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _COMPAT_SYSLOG_H_ +#define _COMPAT_SYSLOG_H_ + + +#ifndef HAVE_SYSLOG +/* For systems without syslog(), provide fake one */ + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 +#define LOG_KERN 0 +#define LOG_USER 8 +#define LOG_MAIL 16 +#define LOG_DAEMON 24 +#define LOG_AUTH 32 +#define LOG_SYSLOG 40 +#define LOG_LPR 48 +#define LOG_NEWS 56 +#define LOG_UUCP 64 +#define LOG_CRON 72 +#define LOG_AUTHPRIV 80 +#define LOG_FTP 88 +#define LOG_LOCAL0 128 +#define LOG_LOCAL1 136 +#define LOG_LOCAL2 144 +#define LOG_LOCAL3 152 +#define LOG_LOCAL4 160 +#define LOG_LOCAL5 168 +#define LOG_LOCAL6 176 +#define LOG_LOCAL7 184 +#define LOG_PID 1 +#define LOG_CONS 2 +#define LOG_ODELAY 4 +#define LOG_NDELAY 8 +#define LOG_NOWAIT 16 +#define LOG_PERROR 32 + +#ifdef __cplusplus +extern "C" { +#endif + +void syslog(int type, const char *fmt, ...); +void vsyslog(int type, const char *fmt, va_list ap); +void openlog(const char *app, int option, int facility); +void closelog(void); + +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __SYSLOG_H */ diff --git a/src/compat_defs.h b/src/compat_defs.h new file mode 100644 index 0000000..25174b8 --- /dev/null +++ b/src/compat_defs.h @@ -0,0 +1,37 @@ +/* vchanger_common.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _COMPAT_DEFS_H_ +#define _COMPAT_DEFS_H_ 1 + +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#define DIR_DELIM "\\" +#define DIR_DELIM_C '\\' +#define MAG_VOLUME_MASK 0 +#else +#define DIR_DELIM "/" +#define DIR_DELIM_C '/' +#define MAG_VOLUME_MASK S_IWGRP|S_IRWXO +#endif + +#endif /* _VCHANGER_COMMON_H_ */ diff --git a/src/diskchanger.cpp b/src/diskchanger.cpp new file mode 100644 index 0000000..9ec678b --- /dev/null +++ b/src/diskchanger.cpp @@ -0,0 +1,993 @@ +/* diskchanger.cpp + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * The bulk of the work gets done by the DiskChanger class, which does + * the actual "loading" and "unloading" of volumes. + */ + +#include "config.h" +#include "compat_defs.h" +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "compat/gettimeofday.h" +#include "compat/readlink.h" +#include "compat/sleep.h" +#include "compat/symlink.h" +#include "util.h" +#include "loghandler.h" +#include "bconsole.h" +#include "diskchanger.h" + + +/*================================================= + * Class DiskChanger + *=================================================*/ + +/*------------------------------------------------- + * destructor + *-------------------------------------------------*/ +DiskChanger::~DiskChanger() +{ + Unlock(); +} + + +/*------------------------------------------------- + * Protected method to read previous state of magazine bays. + * Returns zero on success, else negative and sets lasterr + *-------------------------------------------------*/ +void DiskChanger::InitializeMagazines() +{ + int n; + MagazineState m; + + magazine.clear(); + for (n = 0; (size_t)n < conf.magazine.size(); n++) { + m.SetBay(n, conf.magazine[n].c_str()); + m.prev_num_slots = 0; + m.prev_start_slot = 0; + magazine.push_back(m); + /* Restore previous slot count and starting virtual slot */ + magazine[n].restore(); + /* Get mountpoint and build magazine slot array */ + magazine[n].Mount(); + } +} + + +/*------------------------------------------------- + * Protected method to find the start of an empty range of + * 'count' virtual slots, adding slots if needed. + * Returns the starting slot number of the range found. + *------------------------------------------------*/ +int DiskChanger::FindEmptySlotRange(int count) +{ + VirtualSlot vs; + int start = 0, n = 1, found = 0; + /* Find next empty slot */ + while (n < (int)vslot.size() && vslot[n].mag_bay >= 0) n++; + start = n; + while (n < (int)vslot.size() && found < count) { + if (vslot[n].mag_bay < 0) { + ++found; + ++n; + } else { + found = 0; + while (n < (int)vslot.size() && vslot[n].mag_bay >= 0) n++; + start = n; + } + } + if (found >= count) return start; + while (found < count) { + vs.vs = n++; + vslot.push_back(vs); + ++found; + } + return start; +} + +/*------------------------------------------------- + * Protected method to initialize array of virtual slot and + * assign magazine volumes to virtual slots. When possible, + * volumes are assigned to the same slot they were in + * previously. + *------------------------------------------------*/ +void DiskChanger::InitializeVirtSlots() +{ + int s, m, v, last; + VirtualSlot vs; + bool found; + + /* Create all known slots as initially empty */ + vslot.clear(); + for (s = 0; s <= dconf.max_slot; s++) { + vs.vs = s; + vslot.push_back(vs); + } + /* Re-create virtual slots that existed previously if possible */ + for (m = 0; m < (int)magazine.size(); m++) { + /* Create slots if needed to match max slot used by previous magazines */ + last = magazine[m].prev_start_slot + magazine[m].prev_num_slots; + if (last >= (int)vslot.size()) { + vs.clear(); + while ((int)vslot.size() <= last) { + vs.vs = (int)vslot.size(); + vslot.push_back(vs); + } + } + /* Check this magazine's slots */ + if (magazine[m].empty()) { + log.Info("magazine %d is not mounted", m); + /* magazine is not currently mounted, so will have no slots assigned */ + if (magazine[m].prev_start_slot) { + /* Since it was previously mounted, an 'update slots' is needed */ + log.Warning("update slots needed. magazine %d no longer mounted; previous: %d volumes in slots %d-%d", m, + magazine[m].prev_num_slots, magazine[m].prev_start_slot, + magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1); + needs_update = true; + } + continue; + } + /* Magazine is currently mounted, so check for change in slot assignment */ + log.Info("magazine %d has %d volumes on %s", m, magazine[m].num_slots, + magazine[m].mountpoint.c_str()); + if (magazine[m].num_slots != magazine[m].prev_num_slots) { + /* Number of volumes has changed or magazine was not previously mounted, so + * needs new slot assignment and also 'update slots' will be needed */ + log.Warning("update slots needed. magazine %d has %d volumes, previously had %d", m, + magazine[m].num_slots, magazine[m].prev_num_slots); + needs_update = true; + continue; + } + if (magazine[m].num_slots == 0) { + /* Magazine has no volumes so needs no slot assignment */ + continue; + } + /* Magazine is mounted, was previously mounted, and has the same volume count, + * so attempt to assign to the same slots previously assigned */ + found = false; + for (v = magazine[m].prev_start_slot; v < (int)vslot.size(); v++) { + if (!vslot[v].empty()) { + found = true; + break; + } + } + if (found) { + /* Slot used previously has already been assigned to another magazine. + * Magazine will need to be assigned a new slot range, so an + * 'update slots' will also be needed. */ + log.Warning("update slots needed. magazine %d previous slots %d-%d are not available", m, + magazine[m].prev_start_slot, magazine[m].prev_start_slot + magazine[m].prev_num_slots - 1); + needs_update = true; + continue; + } + /* Assign this magazine's volumes to the same slots as previously assigned */ + magazine[m].start_slot = magazine[m].prev_start_slot; + for (s = 0; s < magazine[m].num_slots; s++) { + v = magazine[m].start_slot + s; + vslot[v].mag_bay = m; + vslot[v].mag_slot = s; + } + log.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m, + magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1); + } + + /* Assign slots to mounted magazines that have not already been assigned. */ + for (m = 0; m < (int)magazine.size(); m++) { + if (magazine[m].empty() || magazine[m].start_slot > 0) continue; + if (magazine[m].num_slots == 0) continue; + magazine[m].start_slot = FindEmptySlotRange(magazine[m].num_slots); + for (s = 0; s < magazine[m].num_slots; s++) { + v = magazine[m].start_slot + s; + vslot[v].mag_bay = m; + vslot[v].mag_slot = s; + } + log.Notice("%d volumes on magazine %d assigned slots %d-%d", magazine[m].num_slots, m, + magazine[m].start_slot, magazine[m].start_slot + magazine[m].num_slots - 1); + } + + /* Save updated state of magazines */ + for (m = 0; m < (int)magazine.size(); m++) { + magazine[m].save(); + } + /* Update dynamic configuration info */ + if ((int)vslot.size() >= dconf.max_slot) { + dconf.max_slot = (int)vslot.size() - 1; + dconf.save(); + } +} + + +/*------------------------------------------------- + * Protected method to initialize state of virtual drives. + * On success, returns zero. On error, returns non-zero. + *------------------------------------------------*/ +int DiskChanger::InitializeDrives() +{ + int n, rc, max_drive = -1; + DIR *d; + struct dirent *de; + DriveState ds; + tString tmp; + + /* For each drive for which a state file exists. try to restore its state */ + d = opendir(conf.work_dir.c_str()); + if (!d) { + rc = errno; + verr.SetErrorWithErrno(rc, "error %d accessing work directory", rc); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + de = readdir(d); + while (de) { + /* Find next drive state file */ + tmp = de->d_name; + if (tmp.find("drive_state-") == 0) { + tmp.erase(0, 12); + if (tmp.find_first_of("0123456789") == tString::npos) { + de = readdir(d); + continue; + } + if (tmp.find_first_not_of("0123456789") != tString::npos) { + de = readdir(d); + continue; + } + n = (int)strtol(tmp.c_str(), NULL, 10); + if (n > max_drive) max_drive = n; + } + de = readdir(d); + } + closedir(d); + if (max_drive < 0) { + /* No drive state files exist, so create at least one drive */ + max_drive = 0; + } + + /* Restore last known state of virtual drives where possible. */ + for (n = 0; n <= max_drive; n++) { + ds.drv = n; + drive.push_back(ds); + /* Attempt to restore drive's last state */ + if (RestoreDriveState(n)) { + log.Error("ERROR! %s", verr.GetErrorMsg()); + } + } + return 0; +} + + +/*------------------------------------------------- + * Protected method to ensure that there are at least n drives + *------------------------------------------------*/ +void DiskChanger::SetMaxDrive(int need) +{ + int n = (int)drive.size(); + DriveState ds; + while (n <= need) { + ds.drv = n++; + drive.push_back(ds); + } +} + +/* + * Method to create symlink for drive pointing to currently loaded volume file + */ +int DiskChanger::CreateDriveSymlink(int drv) +{ + int mag, mslot, rc; + tString sname, fname; + char lname[4096]; + + if (drv < 0 || drv >= (int)drive.size()) { + verr.SetError(EINVAL, "cannot create symlink for invalid drive %d", drv); + return EINVAL; + } + if (drive[drv].vs <= 0) { + verr.SetError(ENOENT, "cannot create symlink for unloaded drive %d", drv); + return ENOENT; + } + mag = vslot[drive[drv].vs].mag_bay; + mslot = vslot[drive[drv].vs].mag_slot; + fname = magazine[mag].GetVolumePath(mslot); + if (fname.empty()) { + verr.SetError(ENOENT, "cannot create symlink for unloaded drive %d", drv); + return ENOENT; + } + tFormat(sname, "%s%s%d", conf.work_dir.c_str(), DIR_DELIM, drv); + rc = readlink(sname.c_str(), lname, sizeof(lname)); + if (rc > 0) { + if (rc >= (int)sizeof(lname)) { + verr.SetError(ENAMETOOLONG, "symlink target too long on readlink for drive %d", drv); + return ENAMETOOLONG; + } + lname[rc] = 0; + if (fname == lname) { + /* symlink already exists */ + log.Info("found symlink for drive %d -> %s", drv, fname.c_str()); + return 0; + } + /* Symlink points to wrong mountpoint, so delete and re-create */ + if (RemoveDriveSymlink(drv)) return EEXIST; + } + if (symlink(fname.c_str(), sname.c_str())) { + rc = errno; + verr.SetErrorWithErrno(rc, "error %d creating symlink for drive %d", rc, drv); + return rc; + } + log.Notice("created symlink for drive %d -> %s", drv, fname.c_str()); + return 0; +} + +/*------------------------------------------------- + * Method to delete this drive's symlink. + * On success returns zero, else on error sets lasterr and + * returns errno. + *-------------------------------------------------*/ +int DiskChanger::RemoveDriveSymlink(int drv) +{ + int rc; + tString sname; + + if (drv < 0 || drv >= (int)drive.size()) { + verr.SetError(EINVAL, "cannot delete symlink for invalid drive %d", drv); + return EINVAL; + } + /* Remove symlink pointing to loaded volume file */ + tFormat(sname, "%s%s%d", conf.work_dir.c_str(), DIR_DELIM, drv); + if (unlink(sname.c_str())) { + if (errno == ENOENT) return 0; /* Ignore if not found */ + /* System error preventing deletion of symlink */ + rc = errno; + verr.SetErrorWithErrno(errno, "error %d deleting symlink for drive %d: ", rc, drv); + return rc; + } + log.Notice("deleted symlink for drive %d", drv); + return 0; +} + + +/*------------------------------------------------- + * Method to save current drive state, device string and + * volume label (filename), to a file in the work + * directory named "drive_state-N", where N is the drive number. + * On success returns zero, else on error sets lasterr and + * returns errno. + *-------------------------------------------------*/ +int DiskChanger::SaveDriveState(int drv) +{ + mode_t old_mask; + FILE *FS; + int rc, mag, mslot; + tString sname; + + if (drv < 0 || drv >= (int)drive.size()) { + verr.SetError(EINVAL, "cannot save state of invalid drive %d", drv); + return EINVAL; + } + /* Delete old state file */ + tFormat(sname, "%s%sdrive_state-%d", conf.work_dir.c_str(), DIR_DELIM, drv); + if (drive[drv].empty()) { + if (access(sname.c_str(), F_OK) == 0) { + log.Notice("deleted state file for drive %d", drv); + } + unlink(sname.c_str()); + return 0; + } + old_mask = umask(027); + FS = fopen(sname.c_str(), "w"); + if (!FS) { + /* Unable to open state file */ + rc = errno; + umask(old_mask); + verr.SetErrorWithErrno(rc, "failed opening state file for drive %d", drv); + return rc; + } + mag = vslot[drive[drv].vs].mag_bay; + mslot = vslot[drive[drv].vs].mag_slot; + if (fprintf(FS, "%s,%s\n", magazine[mag].mag_dev.c_str(), + magazine[mag].GetVolumeLabel(mslot)) < 0) { + /* I/O error writing state file */ + rc = errno; + fclose(FS); + umask(old_mask); + verr.SetErrorWithErrno(rc, "error %d writing state file for drive %d", rc, drv); + return rc; + } + fclose(FS); + umask(old_mask); + log.Notice("wrote state file for drive %d", drv); + return 0; +} + + +/*------------------------------------------------- + * Method to restore drive state from a file in the work directory + * named "drive_state-N", where N is drive_number. If the volume + * previously loaded is available, then restore drive to the loaded + * state, otherwise set drive unloaded and remove the symlink and + * state file for this drive. + * On success returns zero, else on error sets lasterr and + * returns errno. + *-------------------------------------------------*/ +int DiskChanger::RestoreDriveState(int drv) +{ + int rc, v, m, ms; + tString line, dev, labl; + size_t p; + struct stat st; + FILE *FS; + tString sname; + + if (drv < 0 || drv >= (int)drive.size()) { + verr.SetError(EINVAL, "cannot restore state of invalid drive %d", drv); + return EINVAL; + } + drive[drv].clear(); + + /* Check for existing state file */ + tFormat(sname, "%s%sdrive_state-%d", conf.work_dir.c_str(), DIR_DELIM, drv); + if (stat(sname.c_str(), &st)) { + /* drive state file not found, so drive is not loaded */ + RemoveDriveSymlink(drv); + log.Info("drive %d previously unloaded", drv); + return 0; + } + /* Read loaded volume info from state file */ + FS = fopen(sname.c_str(), "r"); + if (!FS) { + /* Error opening state file, so leave drive unloaded */ + verr.SetError(EACCES, "drive %d state file is not readable", drv); + return EACCES; + } + if (tGetLine(line, FS) == NULL) { + if (!feof(FS)) { + /* i/o error reading line from state file. Change state to unloaded */ + rc = ferror(FS); + fclose(FS); + unlink(sname.c_str()); + RemoveDriveSymlink(drv); + verr.SetErrorWithErrno(rc, "error %d reading state file for drive %d", rc, drv); + return rc; + } + } + fclose(FS); + tStrip(tRemoveEOL(line)); + /* Extract the device drive was last loaded from */ + p = 0; + rc = tParseCSV(dev, line, p); + if (rc != 1 || dev.empty()) { + /* Device string not found. Change state to unloaded. */ + verr.SetError(EINVAL, "deleting corrupt state file for drive %d", drv); + unlink(sname.c_str()); + RemoveDriveSymlink(drv); + return EINVAL; + } + /* Extract label of volume drive was last loaded from */ + rc = tParseCSV(labl, line, p); + if (rc != 1 || labl.empty()) { + /* Label string not found. Change state to unloaded. */ + verr.SetError(EINVAL, "deleting corrupt state file for drive %d", drv); + unlink(sname.c_str()); + RemoveDriveSymlink(drv); + return EINVAL; + } + + /* Find virtual slot assigned the volume file last loaded in drive */ + for (v = 1; v < (int)vslot.size(); v++) { + if (labl == GetVolumeLabel(v)) break; + } + if (v >= (int)vslot.size()) { + /* Volume last loaded is no longer available. Change state to unloaded. */ + log.Notice("volume %s no longer available, unloading drive %d", + labl.c_str(), drv); + unlink(sname.c_str()); + RemoveDriveSymlink(drv); + return 0; + } + drive[drv].vs = v; + + /* Ensure symlink exists or create it */ + if ((rc = CreateDriveSymlink(drv)) != 0) { + /* Unable to create symlink */ + drive[drv].vs = -1; + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + + /* Assign drive to virtual slot */ + vslot[v].drv = drv; + m = vslot[v].mag_bay; + ms = vslot[v].mag_slot; + log.Notice("drive %d previously loaded from slot %d (%s)", drv, v, magazine[m].GetVolumeLabel(ms)); + return 0; +} + + +/*------------------------------------------------- + * Method to initialize changer parameters and state of magazines, + * virtual slots, and virtual drives. + * On success, returns zero. On error, returns negative. + * In either case, obtains a lock on the changer unless the lock operation + * itself fails. The lock will be released when the DiskChanger object + * is destroyed. + *------------------------------------------------*/ +int DiskChanger::Initialize() +{ + /* Make sure we have a lock on this changer */ + if (Lock()) return verr.GetError(); + magazine.clear(); + vslot.clear(); + drive.clear(); + dconf.restore(); + needs_update = false; + + /* Initialize array of mounted magazines */ + InitializeMagazines(); + + /* Initialize array of virtual slots */ + InitializeVirtSlots(); + + /* Initialize array of virtual drives */ + if (InitializeDrives()) return verr.GetError(); + + return 0; +} + + +/*------------------------------------------------- + * Method to load virtual drive 'drv' from virtual slot 'slot'. + * Returns zero on success, else sets lasterr and + * returns negative. + *------------------------------------------------*/ +int DiskChanger::LoadDrive(int drv, int slot) +{ + int rc, m, ms; + + if (!changer_lock) { + verr.SetError(EINVAL, "changer not initialized"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + if (drv < 0) { + verr.SetError(EINVAL, "invalid drive number %d", drv); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + SetMaxDrive(drv); + if (slot < 1 || slot >= (int)vslot.size()) { + verr.SetError(EINVAL, "cannot load drive %d from invalid slot %d", drv, slot); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + if (!drive[drv].empty()) { + if (drive[drv].vs == slot) return 0; /* already loaded from this slot */ + verr.SetError(EBUSY, "drive %d already loaded from slot %d", drv, slot); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EBUSY; + } + if (vslot[slot].empty()) { + verr.SetError(EINVAL, "cannot load drive %d from empty slot %d", drv, slot); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return ENOENT; + } + /* Create symlink for drive pointing to volume file */ + drive[drv].vs = slot; + if ((rc = CreateDriveSymlink(drv))) { + drive[drv].vs = -1; + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + /* Save state of newly loaded drive */ + if ((rc = SaveDriveState(drv)) != 0) { + /* Error writing drive state file */ + RemoveDriveSymlink(drv); + drive[drv].vs = -1; + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + /* Assign virtual slot to drive */ + vslot[slot].drv = drv; + m = vslot[slot].mag_bay; + ms = vslot[slot].mag_slot; + log.Notice("loaded drive %d from slot %d (%s)", drv, slot, magazine[m].GetVolumeLabel(ms)); + return 0; +} + + +/*------------------------------------------------- + * Method to unload volume in virtual drive 'drv'. Deletes symlink + * and state file for the drive. + * On success, returns zero. Otherwise sets lasterr and returns + * errno. + *------------------------------------------------*/ +int DiskChanger::UnloadDrive(int drv) +{ + int rc; + + if (!changer_lock) { + verr.SetError(EINVAL, "changer not initialized"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + if (drv < 0) { + verr.SetError(EINVAL, "invalid drive number %d", drv); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EINVAL; + } + SetMaxDrive(drv); + if (drive[drv].empty()) { + /* Drive is already empty so assume successful */ + return 0; + } + /* Remove drive's symlink */ + if ((rc = RemoveDriveSymlink(drv)) != 0) { + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + /* Remove virtual slot assignment */ + vslot[drive[drv].vs].drv = -1; + drive[drv].vs = -1; + /* Update drive state file (will delete state file due to negative slot number) */ + if ((rc = SaveDriveState(drv)) != 0) { + log.Error("ERROR! %s", verr.GetErrorMsg()); + return rc; + } + log.Notice("unloaded drive %d", drv); + return 0; +} + + +/*------------------------------------------------- + * Method to create new volume files in virtual slots 'slot1' through 'slot2'. + * Use volume labels (barcodes) of the form prefix + '_' + mag_slot_number, where + * mag_slot_number is the magazine relative slot number of the magazine slot that + * the virtual slot maps to. If 'label_prefix' is blank, then use the magazine name + * of the magazine the virtual slot is mapped onto as the prefix. + * Returns zero on success, else returns negative and sets lasterr. + *------------------------------------------------*/ +int DiskChanger::CreateVolumes(int bay, int count, int start, const char *label_prefix_in) +{ + MagazineSlot vol; + tString label, label_prefix(label_prefix_in); + int i; + + if (!changer_lock) { + verr.SetError(EINVAL, "changer not initialized"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return -1; + } + if (bay < 0 || bay >= (int)magazine.size()) { + verr.SetError(EINVAL, "invalid magazine"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return -1; + } + if (count < 1) count = 1; + tStrip(tRemoveEOL(label_prefix)); + if (label_prefix.empty()) { + /* Default prefix is storage-name_magazine-number */ + tFormat(label_prefix, "%s_%d", conf.storage_name.c_str(), bay); + } + if (start < 0) { + /* Find highest uniqueness number for this filename prefix */ + for (i = magazine[bay].num_slots * 5; i > 0; i--) { + tFormat(label, "%s_%d", label_prefix.c_str(), i); + if (magazine[bay].GetVolumeSlot(label) >= 0) break; + } + start = i; + } + for (i = 0; i < count; i++) { + tFormat(label, "%s_%d", label_prefix.c_str(), start); + if (!magazine[bay].empty()) { + while (magazine[bay].GetVolumeSlot(label) >= 0) { + ++start; + tFormat(label, "%s_%d", label_prefix.c_str(), start); + } + } + fprintf(stdout, "creating label '%s'\n", label.c_str()); + if (magazine[bay].CreateVolume(label)) { + if (i) magazine[bay].save(); + return -1; + } + ++start; + } + /* Update magazine state */ + magazine[bay].save(); + /* New mag state will require 'update slots' and 'label barcodes' in Bacula */ + needs_update = true; + needs_label = true; + log.Notice("update slots needed. %d volumes added to magazine %d",count , bay); + return 0; +} + +/*------------------------------------------------- + * Method to cause Bacula to update its catalog to reflect + * changes in the available volumes + *-------------------------------------------------*/ +int DiskChanger::UpdateBacula() +{ + int rc; + FILE *update_lock; + tString cmd; + char lockfile[4096]; + + /* Check if update needed */ + if (!needs_update && !needs_label) return 0; /* Nothing to do */ + /* Create update lock lockfile */ + snprintf(lockfile, sizeof(lockfile), "%s%s%s.updatelock", conf.work_dir.c_str(), DIR_DELIM, + conf.storage_name.c_str()); + rc = exclusive_fopen(lockfile, &update_lock); + if (rc == EEXIST) { + /* Update already in progress in another process, so skip */ + return 0; + } + if (rc) { + /* error creating lockfile, so skip */ + log.Error("bconsole: errno=%d creating update lockfile", rc); + if (needs_update) + log.Error("WARNING! 'update slots' needed in bconsole"); + if (needs_label) + log.Error("WARNING! 'label barcodes' needed in bconsole"); + return 0; + } + log.Debug("created update lockfile for pid %d", getpid()); + /* Perform update slots command in bconsole */ + if (needs_update) { + /* Issue update slots command in bconsole */ + tFormat(cmd, "update slots storage=\"%s\"", conf.storage_name.c_str()); + if(issue_bconsole_command(cmd.c_str())) { + log.Error("WARNING! 'update slots' needed in bconsole"); + } + } + /* Perform label barcodes command in bconsole */ + if (needs_label) { + tFormat(cmd, "label storage=\"%s\" pool=\"%s\" barcodes\nyes\nyes\n", conf.storage_name.c_str(), + conf.def_pool.c_str()); + if (issue_bconsole_command(cmd.c_str())) { + log.Error("WARNING! 'label barcodes' needed in bconsole"); + } + } + /* Obtain changer lock before removing update lock */ + fclose(update_lock); + unlink(lockfile); + log.Debug("removed update lockfile for pid %d", getpid()); + return 0; +} + + +/*------------------------------------------------- + * Method to get label of volume in this slot + *-------------------------------------------------*/ +const char* DiskChanger::GetVolumeLabel(int slot) +{ + if (slot <= 0 || slot >= (int)vslot.size()) { + verr.SetError(-1, "volume label request from invalid slot %d", slot); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return NULL; + } + if (vslot[slot].empty()) return ""; + return magazine[vslot[slot].mag_bay].GetVolumeLabel(vslot[slot].mag_slot); +} + + +/*------------------------------------------------- + * Method to get filename path of volume in this slot + *-------------------------------------------------*/ +const char* DiskChanger::GetVolumePath(tString &path, int slot) +{ + path.clear(); + if (slot <= 0 || slot >= (int)vslot.size()) { + verr.SetError(-1, "volume path request from invalid slot %d", slot); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return NULL; + } + if (vslot[slot].empty()) return path.c_str(); + return magazine[vslot[slot].mag_bay].GetVolumePath(path, vslot[slot].mag_slot); +} + + +/*------------------------------------------------- + * Protected method to lock changer device using a lock file such that + * only one process at a time may execute changer commands on the + * same autochanger. If another process has the lock, then this process + * will sleep 1 second before trying again. This try/wait loop will continue + * until the lock is obtained or 'timeout' seconds have expired. If + * timeout = 0 then only tries to obtain lock once. If timeout < 0 + * then doesn't return until the lock is obtained. + * On success, returns true. Otherwise on error or timeout, sets + * lasterr negative and returns false. + *------------------------------------------------*/ +int DiskChanger::Lock(long timeout_seconds) +{ + int rc; + time_t timeout = 0; + char lockfile[4096]; + + if (changer_lock) return 0; + + if (timeout_seconds < 0) { + timeout_seconds = 3600 * 24 * 365; + } + if (timeout_seconds > 0) { + timeout = time(NULL) + timeout_seconds; + } + snprintf(lockfile, sizeof(lockfile), "%s%s%s.lock", conf.work_dir.c_str(), DIR_DELIM, + conf.storage_name.c_str()); + rc = exclusive_fopen(lockfile, &changer_lock); + if (rc == EEXIST && timeout == 0) { + /* timeout=0 means do not wait */ + verr.SetErrorWithErrno(rc, "cannot open lockfile"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return -1; + } + while (rc == EEXIST) { + /* sleep before trying again */ + sleep(1); + if (time(NULL) > timeout) { + verr.SetError(EBUSY, "timeout waiting for lockfile"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return EACCES; + } + rc = exclusive_fopen(lockfile, &changer_lock); + } + if (rc) { + verr.SetErrorWithErrno(rc, "cannot open lockfile"); + log.Error("ERROR! %s", verr.GetErrorMsg()); + return -1; + } + /* Write PID to lockfile and leave open for exclusive R/W */ + fprintf(changer_lock, "%d", getpid()); + fflush(changer_lock); + log.Debug("created lockfile for pid %d", getpid()); + return 0; +} + +/*------------------------------------------------- + * Protected method to unlock changer device + *------------------------------------------------*/ +void DiskChanger::Unlock() +{ + char lockfile[4096]; + if (!changer_lock) return; + fclose(changer_lock); + changer_lock = NULL; + snprintf(lockfile, sizeof(lockfile), "%s%s%s.lock", conf.work_dir.c_str(), DIR_DELIM, + conf.storage_name.c_str()); + log.Debug("removing lockfile for pid %d", getpid()); + unlink(lockfile); +} + + +/*------------------------------------------------- + * Method returns true if magazine is not mounted, + * else returns false. + *------------------------------------------------*/ +bool DiskChanger::MagazineEmpty(int mag) const +{ + if (mag < 0 || mag >= (int)magazine.size()) return true; + return magazine[mag].empty(); +} + + +/*------------------------------------------------- + * Method returns true if no magazine volume is assigned + * to virtual slot, else returns false. + *------------------------------------------------*/ +bool DiskChanger::SlotEmpty(int slot) const +{ + if (slot <= 0 || slot >= (int)vslot.size()) return true; + return vslot[slot].empty(); +} + + +/*------------------------------------------------- + * Method returns true if no magazine volume is loaded + * into drive drv, else returns false. + *------------------------------------------------*/ +bool DiskChanger::DriveEmpty(int drv) const +{ + if (drv < 0 || drv >= (int)drive.size()) return true; + return drive[drv].empty(); +} + + +/*------------------------------------------------- + * Method to get virtual slot currently loaded in virtual drive 'drv'. + * If drive is loaded then returns the virtual slot number of the + * loaded volume. If unloaded, returns zero. + *------------------------------------------------*/ +int DiskChanger::GetDriveSlot(int drv) const +{ + if (drv < 0 || drv >= (int)drive.size()) return 0; + return drive[drv].vs; +} + + +/*------------------------------------------------- + * Method to get drive a virtual slot is currently loaded in. + * Returns the drive number a slot's volume is loaded in. + * If unloaded, returns negative. + *------------------------------------------------*/ +int DiskChanger::GetSlotDrive(int slot) const +{ + if (slot <= 0 || slot >= (int)vslot.size()) return -1; + return vslot[slot].drv; +} + + +/*------------------------------------------------- + * Method to return number of volumes on magazine 'mag'. + *------------------------------------------------*/ +int DiskChanger::GetMagazineSlots(int mag) const +{ + if (mag < 0 || mag >= (int)magazine.size()) return 0; + return magazine[mag].num_slots; +} + + +/*------------------------------------------------- + * Method to return the start of the virtual slot range + * that is assigned to magazine 'mag' volumes. + *------------------------------------------------*/ +int DiskChanger::GetMagazineStartSlot(int mag) const +{ + if (mag < 0 || mag >= (int)magazine.size()) return 0; + return magazine[mag].start_slot; +} + + +/*------------------------------------------------- + * Method to return the mountpoint of magazine 'mag'. + *------------------------------------------------*/ +const char* DiskChanger::GetMagazineMountpoint(int mag) const +{ + if (mag < 0 || mag >= (int)magazine.size()) return ""; + return magazine[mag].mountpoint.c_str(); +} diff --git a/src/diskchanger.h b/src/diskchanger.h new file mode 100644 index 0000000..ef5a01a --- /dev/null +++ b/src/diskchanger.h @@ -0,0 +1,80 @@ +/* diskchanger.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef DISKCHANGER_H_ +#define DISKCHANGER_H_ + +#include "vconf.h" +#include "errhandler.h" +#include "changerstate.h" + +class DiskChanger +{ +public: + DiskChanger() : changer_lock(NULL), needs_update(false), needs_label(false) {} + virtual ~DiskChanger(); + int Initialize(); + int LoadDrive(int drv, int slot); + int UnloadDrive(int drv); + int CreateVolumes(int bay, int count, int start = -1, const char *label_prefix = ""); + int UpdateBacula(); + const char* GetVolumeLabel(int slot); + const char* GetVolumePath(tString &fname, int slot); + bool MagazineEmpty(int bay) const; + bool SlotEmpty(int slot) const; + bool DriveEmpty(int drv) const; + int GetDriveSlot(int drv) const; + int GetSlotDrive(int slot) const; + int GetMagazineSlots(int mag) const; + int GetMagazineStartSlot(int mag) const; + const char* GetMagazineMountpoint(int mag) const; + inline int NumDrives() { return (int)drive.size(); } + inline int NumMagazines() { return (int)magazine.size(); } + inline int NumSlots() { return (int)vslot.size() - 1; } + inline int GetError() { return verr.GetError(); } + inline const char* GetErrorMsg() const { return verr.GetErrorMsg(); } + inline bool NeedsUpdate() const { return needs_update; } + inline bool NeedsLabel() const { return needs_label; } + int Lock(long timeout = 30); + void Unlock(); +protected: + void InitializeMagazines(); + int FindEmptySlotRange(int count); + int InitializeDrives(); + void InitializeVirtSlots(); + void SetMaxDrive(int n); + int CreateDriveSymlink(int drv); + int RemoveDriveSymlink(int drv); + int SaveDriveState(int drv); + int RestoreDriveState(int drv); +protected: + FILE *changer_lock; + bool needs_update; + bool needs_label; + ErrorHandler verr; + DynamicConfig dconf; + MagazineStateArray magazine; + DriveStateArray drive; + VirtualSlotArray vslot; +}; + +#endif /*DISKCHANGER_H_*/ diff --git a/src/errhandler.cpp b/src/errhandler.cpp new file mode 100644 index 0000000..dd5c254 --- /dev/null +++ b/src/errhandler.cpp @@ -0,0 +1,73 @@ +/* errhandler.cpp + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Provides a class for logging messages to a file + */ + +#include "config.h" +#include +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_VARARGS_H +#include +#endif + +#include "errhandler.h" + +/////////////////////////////////////////////////// +// Class ErrorHandler +/////////////////////////////////////////////////// + +/*------------------------------------------------- + * Method to set error and error message + *------------------------------------------------*/ +void ErrorHandler::SetError(int errnum, const char *fmt, ...) +{ + va_list vl; + char buf[4096]; + err = errnum; + va_start(vl, fmt); + vsnprintf(buf, sizeof(buf), fmt, vl); + va_end(vl); + msg = buf; +} + +/*------------------------------------------------- + * Method to set error and error message and append the text + * returned from strerror(errnum). + *------------------------------------------------*/ +void ErrorHandler::SetErrorWithErrno(int errnum, const char *fmt, ...) +{ + va_list vl; + char buf[4096]; + err = errnum; + va_start(vl, fmt); + vsnprintf(buf, sizeof(buf), fmt, vl); + va_end(vl); + msg = buf; + msg += ": "; + msg += strerror(err); +} diff --git a/src/errhandler.h b/src/errhandler.h new file mode 100644 index 0000000..236e405 --- /dev/null +++ b/src/errhandler.h @@ -0,0 +1,43 @@ +/* errhandler.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ +#ifndef _ERRHANDLER_H_ +#define _ERRHANDLER_H_ 1 + +#include "tstring.h" + +class ErrorHandler +{ +public: + ErrorHandler() : err(0) {} + ~ErrorHandler() {} + inline void clear() { err = 0; msg.clear(); } + void SetError(int errnum, const char *fmt, ...); + void SetErrorWithErrno(int errnum, const char *fmt, ...); + inline const char* GetErrorMsg() const { return msg.c_str(); } + inline int GetError() { return err; } +protected: + int err; + tString msg; +}; + +#endif /* _ERRHANDLER_H_ */ diff --git a/src/inifile.cpp b/src/inifile.cpp new file mode 100644 index 0000000..800c748 --- /dev/null +++ b/src/inifile.cpp @@ -0,0 +1,1185 @@ +/* inifile.cpp + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#include "config.h" +#include +#include +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif + +#include "inifile.h" +#include "loghandler.h" + +static tString EMPTY_VAL; + +//////////////////////////////////////////////////////////////////////////////// +// Class IniValue +//////////////////////////////////////////////////////////////////////////////// + +IniValue& IniValue::operator=(const IniValue &b) +{ + if (&b != this) { + type = b.type; + value = b.value; + } + return *this; +} + +IniValue& IniValue::operator=(const tStringArray &b) +{ + value.clear(); + if (b.empty()) return *this; + if (type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + value = b; + return *this; + } + /* For types that allow only one string, use only the first string of b */ + value.push_back(b[0]); + return *this; +} + +IniValue& IniValue::operator=(const tString &b) +{ + value.clear(); + value.push_back(b); /* If b is NULL, then value is cleared */ + return *this; +} + +IniValue& IniValue::operator=(const char *b) +{ + value.clear(); + if (b) value.push_back(b); /* If b is NULL, then value is cleared */ + return *this; +} + +IniValue& IniValue::operator=(long long b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%lld", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(unsigned long long b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%llu", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(long b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%ld", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(unsigned long b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%lu", b); + value.clear(); + value.push_back(buf); + return *this; +} + + +IniValue& IniValue::operator=(int b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%d", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(unsigned int b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%u", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(short b) +{ if (!b) return *this; + + char buf[64]; + snprintf(buf, sizeof(buf), "%hd", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(unsigned short b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%hu", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(char b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%hhd", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(unsigned char b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%hhu", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(long double b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%.21Lg", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(double b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%.17g", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(float b) +{ + char buf[64]; + snprintf(buf, sizeof(buf), "%.8g", b); + value.clear(); + value.push_back(buf); + return *this; +} + +IniValue& IniValue::operator=(bool b) +{ + value.clear(); + if (b) value.push_back("1"); + else value.push_back("0"); + return *this; +} + +IniValue& IniValue::operator+=(const IniValue &b) +{ + tStringArray::const_iterator p; + if (!b.IsSet()) return *this; + if (type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + for (p = b.value.begin(); p != b.value.end(); p++) + value.push_back(*p); + } else { + if (value.empty()) value.push_back(""); + value[0] += b.value[0]; + } + return *this; +} + +IniValue& IniValue::operator+=(const tStringArray &b) +{ + tStringArray::const_iterator p; + if (b.empty()) return *this; + if (type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + for (p = b.begin(); p != b.end(); p++) + value.push_back(*p); + } else { + if (value.empty()) value.push_back(""); + value[0] += b[0]; + } + return *this; +} + +IniValue& IniValue::operator+=(const tString &b) +{ + if (value.empty() || type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + value.push_back(b); + } else { + if (value.empty()) value.push_back(""); + value[0] += b; + } + return *this; +} + +IniValue& IniValue::operator+=(const char *b) +{ + if (!b) return *this; + if (value.empty() || type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + value.push_back(b); + } else { + if (value.empty()) value.push_back(""); + value[0] += b; + } + return *this; +} + +IniValue& IniValue::operator+=(const char c) +{ + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this += buf; + return *this; +} + +size_t IniValue::size() const +{ + if (type == INIKEYWORDTYPE_MULTISZ || type == INIKEYWORDTYPE_SECTION + || type == INIKEYWORDTYPE_ORDERED_SECTION) { + return value.size(); + } + if (value.empty()) return 0; + return value[0].size(); +} + +const char* IniValue::GetSZ() const +{ + if (value.empty()) return ""; + return value[0].c_str(); +} + +const tString& IniValue::GetString() const +{ + if (value.empty()) return EMPTY_VAL; + return value.front(); +} + +long long IniValue::GetLONG() const +{ + if (value.empty()) return 0; + return strtoll(value[0].c_str(), NULL, 10); +} + +unsigned long long IniValue::GetULONG() const +{ + if (value.empty()) return 0; + return strtoull(value[0].c_str(), NULL, 10); +} + +long double IniValue::GetDOUBLE() const +{ + if (value.empty()) return 0; + return strtold(value[0].c_str(), NULL); +} + +bool IniValue::GetBOOL() const +{ + if (value.empty()) return false; + tString v(value[0]); + tToLower(v); + long l = strtol(v.c_str(), NULL, 10); + if (v == "yes" || v == "y" || v == "true" || v == "t" + || v == "on" || (isdigit(v[0]) && l != 0)) return true; + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// Class IniFile +//////////////////////////////////////////////////////////////////////////////// + +IniFile::IniFile(const IniFile &b) +{ + kwmap = b.kwmap; +} + +/* + * Assignment operator + */ +IniFile& IniFile::operator=(const IniFile &b) +{ + if (&b != this) { + kwmap = b.kwmap; + } + return *this; +} + + +/* + * Method to parse key and return section, keyword, and if ordered section, then also ordered section + * base name and the index of the keyword in the section's map entry + */ +bool IniFile::ParseKey(const char *key_in, tString &base, size_t &ndx, tString §, tString &kw) +{ + size_t n; + tString sndx, key(key_in); + base.clear(); + sect.clear(); + kw.clear(); + ndx = 0; + tToLower(tRemoveWS(key)); + if (key.find_first_of("=%,;") != tString::npos) return false; + n = key.find('/'); + if (n == 0) { + key.erase(0, 1); + n = key.find('/'); + if (n == 0) return false; + } + if (key.empty()) return false; + if (n == tString::npos) { + /* Key in global section */ + kw = key; + return true; + } + sect = key.substr(0, n); + kw = key.substr(n + 1); + if (kw.empty()) { + sect.clear(); + return false; + } + n = sect.find_last_not_of("0123456789"); + if (n == tString::npos) { + /* numeric section names are invalid */ + sect.clear(); + kw.clear(); + return false; + } + ++n; + if (n < sect.size()) { + sndx = sect.substr(n); + ndx = strtoul(sndx.c_str(), NULL, 10); + base = sect.substr(0, n); + } + return true; +} + +IniValuePairList::iterator IniFile::FindKey(const char *key_in) +{ + IniValuePairList::iterator p; + tString key(key_in); + tToLower(tRemoveWS(key)); + for (p = kwmap.begin(); p != kwmap.end(); p++) { + if (p->key == key) break; + } + return p; +} + +IniValuePairList::iterator IniFile::FindValue(const char *key) +{ + size_t n, s, ndx; + IniValuePair np; + IniValuePairList::iterator p; + tString sect, kw, base; + + p = FindKey(key); + if (p != kwmap.end()) { + if (p->value.type == INIKEYWORDTYPE_SECTION || p->value.type == INIKEYWORDTYPE_ORDERED_SECTION) + return kwmap.end(); /* a section key has no associated value */ + return p; /* found key's value */ + } + /* For ordered sections, key values are not created in map until they are accessed or assigned. + * Therefore we must determine if this is a valid ordered section key */ + if (!ParseKey(key, base, ndx, sect, kw)) { + /* Invalid key syntax */ + return kwmap.end(); + } + if (base.empty()) { + /* Not an ordered section, so key does not exist */ + return kwmap.end(); + } + p = FindKey(base); + if (p == kwmap.end()) { + /* No such ordered section found */ + return kwmap.end(); + } + if (p->value.type != INIKEYWORDTYPE_ORDERED_SECTION) { + /* Not a valid ordered section */ + return kwmap.end(); + } + /* Check that ordered section defines the given keyword */ + for (s = 0; s < p->value.value.size(); s++) { + n = p->value.value[s].find(','); + if (p->value.value[s].substr(0, n) == kw) break; + } + if (s == p->value.value.size()) { + /* keyword not found for this ordered section */ + return kwmap.end(); + } + /* Found valid ordered section key that needs to be created */ + np.key = sect + '/'; + np.key += kw; + np.value.type = (int)strtol(p->value.value[s].substr(n + 1).c_str(), NULL, 10); + kwmap.push_back(np); + p = kwmap.end(); + --p; + return p; +} + +IniValuePairList::iterator IniFile::FindSection(const char *sect_in) +{ + IniValuePairList::iterator p; + tString sect(sect_in); + tToLower(tRemoveWS(sect)); + if (sect.empty() || sect.find_first_of("=%,;/") != tString::npos) return kwmap.end(); + p = FindKey(sect); + if (p != kwmap.end()) { + if (p->value.type == INIKEYWORDTYPE_SECTION || p->value.type == INIKEYWORDTYPE_ORDERED_SECTION) + return p; /* found section */ + return kwmap.end(); /* key name is not a section */ + } + /* Check for ordered section */ + size_t n = sect.find_last_not_of("0123456789"); + if (n == tString::npos) return kwmap.end(); /* invalid section name */ + sect.erase(n + 1); + p = FindKey(sect); + if (p != kwmap.end() && p->value.type == INIKEYWORDTYPE_ORDERED_SECTION) { + /* found ordered section */ + return p; + } + return kwmap.end(); /* no such section */ +} + +IniValue& IniFile::operator[](const char *key) +{ + IniValuePairList::iterator p = FindValue(key); + if (p != kwmap.end()) return p->value; /* found existing keyword */ + return bogus; +} + +/* + * Method to retrieve section, keyword, and ordered section info of an existing key + * Returns true if key found, else false + */ +bool IniFile::GetKey(const char *key, tString &base, size_t &ndx, tString §, tString &kw) +{ + IniValuePairList::iterator p = FindValue(key); + if (p == kwmap.end()) return false; /* Key not defined */ + return ParseKey(p->key.c_str(), base, ndx, sect, kw); +} + +/* + * Method to add a global keyword to the grammar + */ +bool IniFile::AddKeyword(const char *key, int kwtype) +{ + IniValuePair np; + IniValuePairList::iterator p = FindValue(key); + if (p != kwmap.end()) { + err_msg = "keyword already exists"; + return false; + } + np.key = key; + tToLower(tRemoveWS(np.key)); + if (np.key.find_first_of("/=%,;") != tString::npos) { + err_msg = "invalid keyword"; + return false; + } + if (kwtype < INIKEYWORDTYPE_SZ || kwtype > INIKEYWORDTYPE_BOOL) { + err_msg = "invalid key type"; + return false; + } + np.value.type = kwtype; + kwmap.push_back(np); + return true; +} + +/* + * Method to add a section to the grammar + */ +bool IniFile::AddSection(const char *sect, bool is_ordered) +{ + size_t n; + IniValuePair np; + IniValuePairList::iterator p = FindValue(sect); + + /* Make sure section name is unused */ + if (p != kwmap.end()) { + err_msg = "section name conflicts with an existing global keyword"; + return false; + } + p = FindKey(sect); + if (p != kwmap.end()) { + err_msg = "section name already defined"; + return false; + } + /* Validate section name */ + np.key = sect; + tToLower(tRemoveWS(np.key)); + if (np.key.find_first_of("/=,;") != tString::npos) { + err_msg = "invalid section name"; + return false; /* invalid params */ + } + n = np.key.find_last_not_of("0123456789"); + if (n != tString::npos) { + if (np.key.find_first_not_of("0123456789", n + 1) == tString::npos) { + /* Section base name with trailing numeric is invalid */ + return false; + } + } + if (is_ordered) { + np.value.type = INIKEYWORDTYPE_ORDERED_SECTION; + } else { + np.value.type = INIKEYWORDTYPE_SECTION; + } + kwmap.push_back(np); + return true; +} + +/* + * Method to add a section specific keyword to the grammar + */ +bool IniFile::AddSectionKeyword(const char *sect_in, const char *kw_in, int kwtype) +{ + size_t n, s, ndx; + IniValuePairList::iterator p; + IniValuePair np; + tString kw, sect, base, buf; + char cbuf[64]; + + if (kwtype < INIKEYWORDTYPE_SZ || kwtype > INIKEYWORDTYPE_BOOL) { + err_msg = "invalid value type"; + return false; + } + p = FindKey(sect_in); + if (p == kwmap.end()) { + err_msg = "no such section"; + return false; + } + /* Check for section keyword already defined */ + buf = p->key + '/'; + buf += kw_in; + if (!ParseKey(buf, base, ndx, sect, kw)) { + err_msg = "invalid keyword"; + return false; + } + for (s = 0; s < p->value.value.size(); s++) { + n = p->value.value[s].find(','); + if (p->value.value[s].substr(0, n) == kw) break; + } + if (s < p->value.value.size()) { + err_msg = "duplicate keyword defined for this section"; + return false; + } + /* Add keyword to this section's list of valid keywords */ + snprintf(cbuf, sizeof(cbuf), ",%d", kwtype); + buf = kw + cbuf; + p->value.value.push_back(buf); + /* For unordered sections, add full keyword to map */ + if (p->value.type == INIKEYWORDTYPE_SECTION) { + np.key = sect + '/'; + np.key += kw; + np.value.type = kwtype; + kwmap.push_back(np); + } + return true; +} + + +/* + * Method to clear value of all keywords + */ +void IniFile::ClearKeywordValues() +{ + IniValuePairList::iterator p; + for (p = kwmap.begin(); p != kwmap.end(); p++) { + if (p->value.type != INIKEYWORDTYPE_SECTION + && p->value.type != INIKEYWORDTYPE_ORDERED_SECTION) { + p->value.clear(); + } + } +} + +/* + * Method to update keyword values with values from keywords + * in b that have been set. + */ +bool IniFile::Update(const IniFile &b) +{ + IniValuePairList::iterator p; + IniValuePairList::const_iterator pb; + for (pb = b.kwmap.begin(); pb != b.kwmap.end(); pb++) { + /* Skip section entries */ + if (pb->value.type == INIKEYWORDTYPE_SECTION + || pb->value.type == INIKEYWORDTYPE_ORDERED_SECTION) continue; + /* Find key in this matching key in b */ + p = FindValue(pb->key.c_str()); + if (p == kwmap.end()) { + /* Key not found */ + err_msg = "key '" + pb->key + "' is not defined"; + return false; + } + /* Found key in this matching key in b */ + if (pb->value.IsSet()) { + /* Update from values in b that have been set */ + if (p->value.type == INIKEYWORDTYPE_MULTISZ) { + /* For string list value types, an update appends b's value to this */ + if (pb->value.value.empty() || pb->value.value[0].empty()) { + /* An empty value acts as a reset, clearing existing values */ + p->value.clear(); + } else { + p->value += pb->value; + } + } else { + /* For all other types, b value replaces existing value */ + p->value = pb->value; + } + } + } + return true; +} + +/* + * Method to get list of valid keywords + */ +size_t IniFile::GetKeywords(tStringArray &kw) +{ + size_t n, v; + tString sect, tmp; + IniValuePairList::iterator p; + kw.clear(); + for (p = kwmap.begin(); p != kwmap.end(); p++) + { + if (p->value.type == INIKEYWORDTYPE_SECTION) { + /* add this unordered section's keywords */ + sect = p->key + "/"; + for (v = 0; v < p->value.value.size(); v++) { + n = p->value.value[v].find(','); + kw.push_back(sect + p->value.value[v].substr(0, n)); + } + } else if (p->value.type == INIKEYWORDTYPE_ORDERED_SECTION) { + /* add this ordered section's keywords */ + sect = p->key + "%lu/"; + for (v = 0; v < p->value.value.size(); v++) { + n = p->value.value[v].find(','); + kw.push_back(sect + p->value.value[v].substr(0, n)); + } + } else { + /* Add global section keywords */ + if (p->key.find('/') == tString::npos) + kw.push_back(p->key); + } + } + return kw.size(); +} + +/* + * Method to get list of keywords that have been assigned values + */ +size_t IniFile::GetSetKeywords(tStringArray &kw) +{ + IniValuePairList::iterator p; + kw.clear(); + for (p = kwmap.begin(); p != kwmap.end(); p++) + { + if (p->value.type == INIKEYWORDTYPE_SECTION + || p->value.type == INIKEYWORDTYPE_ORDERED_SECTION) continue; + if (p->value.IsSet()) { + kw.push_back(p->key); + } + } + return kw.size(); +} + + +/* + * Method to parse keyword/value pairs from a file + * returns: + * 0 EOF + * -1 I/O error + * -2 quoted string missing closing quote + * -3 invalid escape sequence + * ' ' string of blank chars + * '\n' newline + * '[' [ + * ']' ] + * '=' = + * 'S' qouted string + * 'A' atom text + */ +int IniFile::ReadToken(FILE* fs, tString &str) +{ + tString word, tmp, special = "=[]\\\n"; + int c, delim = 0, esc = 0; + + str.clear(); + c = fgetc(fs); + /* Strip comments */ + if (c == ';' || c == '#') { + c = fgetc(fs); + while (c != EOF && c != '\n') { + c = fgetc(fs); + } + } + /* Check for EOF */ + if (c == EOF) { + if (ferror(fs)) return -1; /* i/o error */ + return 0; /* normal end of file */ + } + /* Special handling for CRLF line endings */ + if (c == '\r') { + c = fgetc(fs); + if (c != '\n') return -1; /* CR not followed by LF is an error */ + } + /* Look for single char tokens */ + if (special.find((char)c) != tString::npos) { + str = (char)c; + return c; + } + /* look for space token */ + if (c == ' ' || c == '\t') { + while (c == ' ' || c == '\t') { + str += (char)c; + c = fgetc(fs); + } + if (c != EOF) ungetc(c, fs); + return ' '; + } + /* look for quoted string token */ + if (c == '"' || c == '\'') { + delim = c; + c = fgetc(fs); + while (c != EOF) { + if (!esc) { + if (c == delim) return 'S'; + if (c == '\\') esc = 1; + else str += (char)c; + } else { + switch (c) + { + case '0': + str += '\0'; + break; + case 'r': + str += '\r'; + break; + case 'n': + str += '\n'; + break; + case 't': + str += '\t'; + break; + case 'x': + tmp.clear(); + c = fgetc(fs); + while (c != EOF && tmp.size() < 2 && isxdigit(c)) { + tmp += tolower(c); + c = fgetc(fs); + } + if (c != EOF) ungetc(c, fs); + if (tmp.empty()) return -3; + str += (char)strtol(tmp.c_str(), NULL, 16); + break; + default: + str += (char)c; + break; + } + esc = 0; + } + c = fgetc(fs); + } + return -2; /* closing delimiter not found */ + } + /* look for atom */ + while (c != EOF && c != '"' && c != '\'' && c != ' ' && c != '\t' && c + != '=' && c != '[' && c != ']' && c != '\r' && c != '\n' && c != '\\') { + str += (char)c; + c = fgetc(fs); + } + if (c != EOF) ungetc(c, fs); + return 'A'; +} + +/* + * Method to parse keyword/value pairs from a file + */ +int IniFile::Read(const char *fname) +{ + if (!fname || !strlen(fname)) { + err_msg = "filename is empty or null"; + return -1; + } + FILE* fin = fopen(fname, "r"); + if (!fin) { + err_msg = fname; + err_msg += " not found"; + return -1; + } + int result = Read(fin); + fclose(fin); + return result; +} + +/* + * Method to parse keyword/value pairs from an open file + */ +int IniFile::Read(FILE *fin) +{ + int tok, state = 0, linenum = 1; + tString word, section; + tString kw, kwtmp, val, tmp; + tString skw_name, sval; + tStringArray kwlist; + IniValue ival; + IniValuePairList::iterator p = kwmap.end(), ps; + char buf[4096]; + + err_msg.clear(); + if (!fin || ferror(fin)) { + err_msg = "bad file stream"; + return -1; + } + if (feof(fin)) return 0; + + tok = ReadToken(fin, word); + while (tok > 0) { + switch (state) + { + case 0: + /* Looking for start of token */ + switch (tok) + { + case '\n': + ++linenum; + break; + case ' ': + break; + case '[': + state = 5; + break; + case 'A': + kwtmp = word; + state = 1; + break; + default: + snprintf(buf, sizeof(buf), "syntax error on line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 1: + /* Reading keyword */ + switch (tok) + { + case ' ': + break; + case 'A': + kwtmp += word; + break; + case '=': + /* Found '=' marking end of keyword */ + if (section.empty()) kw.clear(); + else kw = section + "/"; + kw += kwtmp; + val.clear(); + /* Check that keyword is defined */ + p = FindValue(kw); + if (p == kwmap.end()) { + snprintf(buf, sizeof(buf), "unknown keyword '%s' on line %d", kw.c_str(), linenum); + err_msg = buf; + return linenum; + } + state = 2; + break; + default: + snprintf(buf, sizeof(buf), "invalid keyword on line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 2: + /* find start of value */ + switch (tok) + { + case ' ': + break; + case '\\': + state = 18; + break; + case ',': + /* comma is first token of value */ + if (p->value.type == INIKEYWORDTYPE_MULTISZ) { + p->value += ""; + state = 7; + } else { + val = word; + state = 3; + } + break; + case '\n': + /* No value given means keyword's value should be cleared */ + p->value.clear(); + p = kwmap.end(); + ++linenum; + state = 0; + break; + default: + /* Found first word of value */ + val = word; + if (p->value.type == INIKEYWORDTYPE_MULTISZ) + state = 7; + else + state = 3; + break; + } + break; + case 3: + /* reading value */ + switch (tok) + { + case '\\': + /* Found line continuation */ + state = 4; + break; + case '\n': + /* End of line marks end of value */ + p->value = val; + p = kwmap.end(); + ++linenum; + state = 0; + break; + default: + val += word; + break; + } + break; + case 4: + /* looking for continuation line */ + switch (tok) + { + case ' ': + break; + case '\n': + /* Found EOL after line continuation symbol '/' */ + ++linenum; + if (p->value.type == INIKEYWORDTYPE_MULTISZ) + state = 7; + else + state = 3; + break; + default: + snprintf(buf, sizeof(buf), "invalid continuation of line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 5: + /* Find section name following '[' */ + switch (tok) + { + case ' ': + break; + case 'A': + /* Found first word of section name */ + section = word; + state = 6; + break; + case ']': + /* blank or empty section name means return scope to global section */ + section.clear(); + state = 0; + break; + default: + snprintf(buf, sizeof(buf), "invalid section name on line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 6: + /* Reading section name */ + switch (tok) + { + case ' ': + break; + case 'A': + section += word; + break; + case ']': + /* Found section name */ + tToLower(section); + if (section == "global") { + /* return scope to global section */ + section.clear(); + state = 0; + break; + } + if (section.find_first_of("/=,;%") != tString::npos) { + snprintf(buf, sizeof(buf), "invalid section name on line %d", linenum); + err_msg = buf; + return linenum; + } + /* Check that section name is defined */ + ps = FindSection(section); + if (ps == kwmap.end()) { + /* Section not defined */ + snprintf(buf, sizeof(buf), "invalid section name on line %d", linenum); + err_msg = buf; + return linenum; + } + state = 0; + break; + default: + snprintf(buf, sizeof(buf), "invalid section name on line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 7: + /* Reading a multi_sz keyword's value */ + switch (tok) + { + case '\\': + state = 4; + break; + case ',': + p->value += val; + val.clear(); + state = 8; + break; + case '\n': + p->value += val; + p = kwmap.end(); + ++linenum; + val.clear(); + state = 0; + break; + default: + val += word; + break; + } + break; + case 8: + switch (tok) + { + case '\\': + state = 9; + break; + case ' ': + break; + case ',': + p->value += ""; + break; + case '\n': + p->value += ""; + p = kwmap.end(); + ++linenum; + val.clear(); + state = 0; + break; + default: + val = word; + state = 7; + break; + } + break; + case 9: + /* continuation found after comma while looking for begin of value */ + switch (tok) + { + case ' ': + break; + case '\n': + ++linenum; + state = 8; + break; + default: + snprintf(buf, sizeof(buf), "invalid continuation of line %d", linenum); + err_msg = buf; + return linenum; + } + break; + case 18: + /* continuation found while looking for begin of value */ + switch (tok) + { + case ' ': + break; + case '\n': + ++linenum; + state = 2; + break; + default: + snprintf(buf, sizeof(buf), "invalid continuation of line %d", linenum); + err_msg = buf; + return linenum; + } + break; + } + tok = ReadToken(fin, word); + } + + /* Check state at EOF for error */ + if (tok < 0) { + err_msg = "file i/o error"; + return -1; + } + switch (state) + { + case 2: + // found keyword, but EOF before value + p->value.clear(); + break; + case 3: + // EOF before LF reading value + p->value = val; + break; + case 7: + // EOF before LF reading MULTISZ value + p->value += val; + break; + case 8: + // EOF after comma reading MULTISZ value + p->value += ""; + break; + case 1: + // EOF before '=' reading keyword + snprintf(buf, sizeof(buf), "invalid keyword on line %d", linenum); + err_msg = buf; + return linenum; + case 4: + case 9: + case 18: + // EOF follows a line continuation + snprintf(buf, sizeof(buf), "invalid continuation on line %d", linenum); + err_msg = buf; + return linenum; + case 5: + case 6: + // EOF before closing ']' reading section name + snprintf(buf, sizeof(buf), "invalid section name on line %d", linenum); + err_msg = buf; + return linenum; + } + + return 0; +} diff --git a/src/inifile.h b/src/inifile.h new file mode 100644 index 0000000..cd17582 --- /dev/null +++ b/src/inifile.h @@ -0,0 +1,190 @@ +/* inifile.h + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#ifndef _INIPARSE_H_ +#define _INIPARSE_H_ 1 + +#include +#include "tstring.h" + +#define INIKEYWORDTYPE_SECTION 0 +#define INIKEYWORDTYPE_ORDERED_SECTION 1 +#define INIKEYWORDTYPE_SZ 2 +#define INIKEYWORDTYPE_MULTISZ 3 +#define INIKEYWORDTYPE_LONGLONG 4 +#define INIKEYWORDTYPE_ULONGLONG 5 +#define INIKEYWORDTYPE_LONG 6 +#define INIKEYWORDTYPE_ULONG 7 +#define INIKEYWORDTYPE_INT 8 +#define INIKEYWORDTYPE_UINT 9 +#define INIKEYWORDTYPE_SHORT 10 +#define INIKEYWORDTYPE_USHORT 11 +#define INIKEYWORDTYPE_CHAR 12 +#define INIKEYWORDTYPE_UCHAR 13 +#define INIKEYWORDTYPE_LONGDOUBLE 14 +#define INIKEYWORDTYPE_DOUBLE 15 +#define INIKEYWORDTYPE_FLOAT 16 +#define INIKEYWORDTYPE_BOOL 17 + +class IniValue +{ +public: + IniValue() : type(INIKEYWORDTYPE_SZ) {} + IniValue(const IniValue &b) : type(b.type), value(b.value) {} + virtual ~IniValue() {} + IniValue& operator=(const IniValue &b); + IniValue& operator=(const tStringArray &b); + IniValue& operator=(const tString &b); + IniValue& operator=(const char *b); + IniValue& operator=(long long b); + IniValue& operator=(unsigned long long b); + IniValue& operator=(long b); + IniValue& operator=(unsigned long b); + IniValue& operator=(int b); + IniValue& operator=(unsigned int b); + IniValue& operator=(short b); + IniValue& operator=(unsigned short b); + IniValue& operator=(char b); + IniValue& operator=(unsigned char b); + IniValue& operator=(long double b); + IniValue& operator=(double b); + IniValue& operator=(float b); + IniValue& operator=(bool b); + IniValue& operator+=(const IniValue &b); + IniValue& operator+=(const tStringArray &b); + IniValue& operator+=(const tString &b); + IniValue& operator+=(const char *b); + IniValue& operator+=(const char c); + long long GetLONG() const; + unsigned long long GetULONG() const; + long double GetDOUBLE() const; + bool GetBOOL() const; + const char* GetSZ() const; + const tString& GetString() const; + size_t size() const; + inline void SetType(int newtype) { type = newtype; } + inline void clear() { value.clear(); } + inline int GetType() const { return type; } + inline bool empty() const { return size() == 0; } + inline bool IsSet() const { return value.size() != 0; } + inline operator long long() { return GetLONG(); } + inline operator unsigned long long() { return GetULONG(); } + inline operator long() { return (long)GetLONG(); } + inline operator unsigned long() { return (unsigned long)GetULONG(); } + inline operator int() { return (int)GetULONG(); } + inline operator unsigned int() { return (unsigned int)GetULONG(); } + inline operator short() { return (short)GetULONG(); } + inline operator unsigned short() { return (unsigned short)GetULONG(); } + inline operator char() { return (char)GetULONG(); } + inline operator unsigned char() { return (unsigned char)GetULONG(); } + inline operator long double() { return GetDOUBLE(); } + inline operator double() { return (double)GetDOUBLE(); } + inline operator float() { return (float)GetDOUBLE(); } + inline operator bool() { return GetBOOL(); } + inline operator const char*() const { return GetSZ(); } + inline operator const tString&() const { return GetString(); } + inline operator const tStringArray&() const { return value; } + friend class IniFile; +protected: + int type; + tStringArray value; +}; + + +class IniValuePair +{ +public: + IniValuePair() {} + virtual ~IniValuePair() {} + inline IniValuePair& operator=(const IniValuePair &b) + { + if (&b != this) { + key = b.key; + value = b.value; + } + return *this; + } +public: + tString key; + IniValue value; +}; + +typedef std::list IniValuePairList; + +class IniFile +{ +public: + IniFile() {} + IniFile(const IniFile &b); + virtual ~IniFile() {} + IniFile& operator=(const IniFile &b); + IniValue& operator[](const char *key); + inline IniValue& operator[](const tString &key) { return operator[](key.c_str()); } + inline const IniValue& operator[](const char *key) const + { return (const IniValue&)((*this)[key]); } + inline const IniValue& operator[](const tString &key) const + { return (const IniValue&)((*this)[key.c_str()]); } + bool AddKeyword(const char *kw, int kwtype = INIKEYWORDTYPE_SZ); + inline bool AddKeyword(const tString &kw, int kwtype = INIKEYWORDTYPE_SZ) + { return AddKeyword(kw.c_str(), kwtype); } + bool AddSection(const char *sect, bool is_ordered = false); + inline bool AddSection(const tString §, bool is_ordered = false) + { return AddSection(sect.c_str(), is_ordered); } + bool AddSectionKeyword(const char *sect, const char *kw, int kwtype = INIKEYWORDTYPE_SZ); + inline bool AddSectionKeyword(const tString §, const char *kw, int kwtype = INIKEYWORDTYPE_SZ) + { return AddSectionKeyword(sect.c_str(), kw, kwtype); } + inline bool AddSectionKeyword(const char *sect, const tString &kw, int kwtype = INIKEYWORDTYPE_SZ) + { return AddSectionKeyword(sect, kw.c_str(), kwtype); } + inline bool AddSectionKeyword(const tString §, const tString &kw, int kwtype = INIKEYWORDTYPE_SZ) + { return AddSectionKeyword(sect.c_str(), kw.c_str(), kwtype); } + inline bool KeywordExists(const char *kw) { return FindValue(kw) != kwmap.end(); } + inline bool KeywordExists(const tString &kw) { return FindValue(kw.c_str()) != kwmap.end(); } + inline bool SectionExists(const char *sect) { return FindSection(sect) != kwmap.end(); } + inline bool SectionExists(const tString §) { return FindSection(sect.c_str()) != kwmap.end(); } + bool GetKey(const char *key, tString &base, size_t &ndx, tString §, tString &kw); + bool GetKey(const tString &key, tString &base, size_t &ndx, tString §, tString &kw) + { return GetKey(key.c_str(), base, ndx, sect, kw); } + void ClearKeywordValues(); + bool Update(const IniFile &b); + int Read(FILE* stream_in); + int Read(const char *fname); + inline int Read(const tString &fname) { return Read(fname.c_str()); } + size_t GetSetKeywords(tStringArray &kw); + size_t GetKeywords(tStringArray &kw); + inline void clear() { kwmap.clear(); } + inline bool empty() { return kwmap.empty(); } + inline tString GetErrorMessage() { return err_msg; } +protected: + bool ParseKey(const char *key, tString &base, size_t &ndx, tString §, tString &kw); + inline bool ParseKey(const tString &key, tString &base, size_t &ndx, tString §, tString &kw) + { return ParseKey(key.c_str(), base, ndx, sect, kw); } + IniValuePairList::iterator FindKey(const char *key); + inline IniValuePairList::iterator FindKey(const tString &key) { return FindKey(key.c_str()); } + IniValuePairList::iterator FindValue(const char *key); + inline IniValuePairList::iterator FindValue(const tString &key) { return FindValue(key.c_str()); } + IniValuePairList::iterator FindSection(const char *sect); + inline IniValuePairList::iterator FindSection(const tString §) { return FindSection(sect.c_str()); } + int ReadToken(FILE* fs, tString &str); +protected: + IniValuePairList kwmap; + IniValue bogus; + tString err_msg; +}; + +#endif /* _INIPARSE_H_ */ diff --git a/src/loghandler.cpp b/src/loghandler.cpp new file mode 100644 index 0000000..7e963d9 --- /dev/null +++ b/src/loghandler.cpp @@ -0,0 +1,206 @@ +/* loghandler.cpp + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#include "config.h" +#include "compat_defs.h" +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifndef HAVE_LOCALTIME_R +#include "compat/localtime_r.h" +#endif +#define LOGHANDLER_SOURCE 1 +#include "loghandler.h" + +LogHandler log; + +LogHandler::LogHandler() : use_syslog(false), max_debug_level(LOG_WARNING), errfs(stderr) +{ +#ifdef HAVE_PTHREAD_H + pthread_mutex_init(&mut, NULL); +#endif +} + +LogHandler::~LogHandler() +{ + if (use_syslog) closelog(); +#ifdef HAVE_PTHREAD_H + pthread_mutex_destroy(&mut); +#endif +} + +void LogHandler::OpenLog(FILE *fs, int max_level) +{ + Lock(); + if (use_syslog) closelog(); + if (max_level < LOG_EMERG || max_level > LOG_DEBUG) max_level = LOG_DEBUG; + errfs = fs; + use_syslog = false; + max_debug_level = max_level; + Unlock(); +} + +void LogHandler::OpenLog(const char *ident, int facility, int max_level, + int syslog_options) +{ + Lock(); + if (use_syslog) closelog(); + if (facility < LOG_KERN || facility > LOG_LOCAL7) facility = LOG_DAEMON; + if (max_level < LOG_EMERG || max_level > LOG_DEBUG) max_level = LOG_DEBUG; + openlog(ident, syslog_options, facility); + use_syslog = true; + errfs = stderr; + if (errfs == NULL) errfs = stderr; + max_debug_level = max_level; + Unlock(); +} + +void LogHandler::Emergency(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_EMERG, fmt, vl); + va_end(vl); +} + +void LogHandler::Alert(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_ALERT, fmt, vl); + va_end(vl); +} + +void LogHandler::Critical(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_CRIT, fmt, vl); + va_end(vl); +} + +void LogHandler::Error(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_ERR, fmt, vl); + va_end(vl); +} + +void LogHandler::Warning(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_WARNING, fmt, vl); + va_end(vl); +} + +void LogHandler::Notice(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_NOTICE, fmt, vl); + va_end(vl); +} + +void LogHandler::Info(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_INFO, fmt, vl); + va_end(vl); +} + +void LogHandler::Debug(const char *fmt, ...) +{ + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_DEBUG, fmt, vl); + va_end(vl); +} + +void LogHandler::MajorDebug(const char *fmt, ...) +{ +#ifdef MAJOR_DEBUG + va_list vl; + va_start(vl, fmt); + WriteLog(LOG_DEBUG, fmt, vl); + va_end(vl); +#endif +} + +// Method to acquire mutex lock +void LogHandler::Lock() +{ +#ifdef HAVE_PTHREAD_H + pthread_mutex_lock(&mut); +#endif +} + +// Method to release mutex lock +void LogHandler::Unlock() +{ +#ifdef HAVE_PTHREAD_H + pthread_mutex_unlock(&mut); +#endif +} + +// Method to write to log +void LogHandler::WriteLog(int priority, const char *fmt, va_list vl) +{ + size_t n; + struct tm bt; + time_t t; + char buf[1024]; + Lock(); + if (priority > max_debug_level || priority < LOG_EMERG || !fmt) { + Unlock(); + return; + } + t = time(NULL); + localtime_r(&t, &bt); + strftime(buf, 100, "%b %d %T: ", &bt); + strncpy(buf + strlen(buf), fmt, sizeof(buf) - strlen(buf)); + if (use_syslog) vsyslog(priority, buf, vl); + else { + n = strlen(buf); + if (!n) { + fprintf(errfs, "\n"); + } else { + vfprintf(errfs, buf, vl); + if (buf[n - 1] != '\n') { + fprintf(errfs, "\n"); + } + fflush(errfs); + } + } + Unlock(); +} diff --git a/src/loghandler.h b/src/loghandler.h new file mode 100644 index 0000000..e558150 --- /dev/null +++ b/src/loghandler.h @@ -0,0 +1,70 @@ +/* loghandler.h + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#ifndef _LOGHANDLER_H_ +#define _LOGHANDLER_H_ 1 + +#ifdef HAVE_SYSLOG_H +#include +#else +#include "compat/syslog.h" +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_PTHREAD_H +#include +#endif + +class LogHandler +{ +public: + LogHandler(); + virtual ~LogHandler(); + void OpenLog(FILE *fs, int max_level = LOG_WARNING); + void OpenLog(const char *ident = NULL, int facility = LOG_DAEMON, + int max_level = LOG_WARNING, int syslog_options = 0); + void Emergency(const char *fmt, ... ); + void Alert(const char *fmt, ... ); + void Critical(const char *fmt, ... ); + void Error(const char *fmt, ... ); + void Warning(const char *fmt, ... ); + void Notice(const char *fmt, ... ); + void Info(const char *fmt, ... ); + void Debug(const char *fmt, ... ); + void MajorDebug(const char *fmt, ... ); + inline bool UsingSyslog() { return use_syslog; } +protected: + void Lock(); + void Unlock(); + void WriteLog(int priority, const char *fmt, va_list vl); +protected: + bool use_syslog; + int max_debug_level; + FILE *errfs; +#ifdef HAVE_PTHREAD_H + pthread_mutex_t mut; +#endif +}; + +#ifndef LOGHANDLER_SOURCE +extern LogHandler log; +#endif + +#endif /* _LOGHANDLER_H_ */ diff --git a/src/mypopen.cpp b/src/mypopen.cpp new file mode 100644 index 0000000..9bf425d --- /dev/null +++ b/src/mypopen.cpp @@ -0,0 +1,726 @@ +/* mypopen.cpp + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#include "config.h" +#include +#include +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#include "loghandler.h" +#include "mypopen.h" + +/* + * Function to parse command line into argv and argc. + * cmd is command line to be executed. Arguments in cmd will be + * parsed and copied to buffer. On output, each element of argv[] + * will point to a NULL-terminated string located in buffer. + * argv[0] will point to the command and argc will be updated to + * indicate the number of arguments found (including the command + * in argv[0]). On input, if *argv_in is NULL, then memory for + * the argv[] array will be allocated and the caller will be + * responsible for freeing it. If *argv_in is non-null, then + * *argc must be set to the max number of elements that *argv_in + * can hold, including the terminating NULL pointer. + */ +static int mypopen_args(const char *cmd, char* (&argv)[50], int &argc, char *buffer, size_t buffer_sz) +{ + char quote, *b, *b1; + const char *p; + int maxargs = 50; + + /* Initialize arg array */ + if (argc < 2) return -1; + maxargs = argc; + argc = 0; + memset(argv, 0, maxargs * sizeof(char*)); + /* Initialize arg buffer */ + if (strlen(cmd) + 1 >= buffer_sz) return -1; + *buffer = '\0'; + + /* Parse args */ + b = buffer; + p = cmd; + b1 = b; + --maxargs; /* Ensure room for trailing NULL arg ptr */ + while (*p) { + /* skip whitespace between args */ + if (isspace(*p)) { + ++p; + continue; + } + /* Copy next arg to buffer */ + if (*p == '"' || *p == '\'') { + /* Quoted string is treated as one arg */ + quote = *p; + ++p; + while (*p && *p != quote) { + if (*p == '\\') { + ++p; + if (*p == 0) break; + } + *b = *p; + ++b; + ++p; + } + } else { + /* Arg is space-delimited */ + while (*p && !isspace(*p)) { + *b = *p; + ++b; + ++p; + } + } + *b = '\0'; + ++b; + /* Set argument array pointer */ + argv[argc] = b1; + /* Position to next arg */ + b1 = b; + argc += 1; + if (argc >= maxargs) { + /* Max args exceeded */ + argc = 0; + return -1; + } + } + /* Check for no args at all */ + if (argc == 0) { + return -1; + } + + return 0; +} + + +/* + * Function to close all pipes that may be open + */ +static void CloseAllPipes(int *pipe_in, int *pipe_out, int *pipe_err) +{ + if (pipe_in[0] >= 0) close(pipe_in[0]); + if (pipe_in[1] >= 0) close(pipe_in[1]); + if (pipe_out[0] >= 0) close(pipe_out[0]); + if (pipe_out[1] >= 0) close(pipe_out[1]); + if (pipe_err[0] >= 0) close(pipe_err[0]); + if (pipe_err[1] >= 0) close(pipe_err[1]); +} + + + +/* + * Function to fork a child process, specifying the command and arguments to be + * run in the child and the child's standard i/o files. If fno_stdXXX is NULL, + * then the child will inherit the parent's stdXXX. If *fno_stdXXX is -1, then + * a pipe will be created with the child's stdXXX being one end of the pipe and + * the other end of the pipe being passed back to the caller in *fno_stdXXX. If + * *fno_stdXXX is zero or greater, then it specifies a file descriptor that will be + * used as the corresponding stdXXX in the child. + * On success, returns the pid of the child. On error, returns -1 and sets errno. + */ +#ifndef HAVE_WINDOWS_H +static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, int *fno_stderr) +{ + int rc, pipe_in[2], pipe_out[2], pipe_err[2]; + int n, pid = -1, argc = 50; + char* argv[50]; + char argbuf[4096]; + + /* Sanity check parameters */ + if (!cline || !cline[0]) { + errno = EINVAL; + return -1; + } + for (n = 0; n < 2; n++) + { + pipe_in[n] = -1; + pipe_out[n] = -1; + pipe_err[n] = -1; + } + + /* Build argv array from command line string */ + if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) { + /* Invalid args, so terminate child */ + log.Debug("popen: invalid cmdline args for child"); + errno = EINVAL; + return -1; + } + + /* Setup child's stdin */ + if (fno_stdin) { + if (*fno_stdin < 0) { + /* Caller requests a pipe by specifying descriptor -1 */ + rc = pipe(pipe_in); + if (rc) { + /* error creating pipe */ + return -1; + } + log.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]); + } else if (*fno_stdin == STDIN_FILENO) { + /* Caller specified stdin so just let child inherit it */ + fno_stdin = NULL; + } + } + + /* Setup child's stdout */ + if (fno_stdout) { + if (*fno_stdout < 0) { + /* Caller requests a pipe by specifying descriptor -1 */ + rc = pipe(pipe_out); + if (rc) { + /* error creating pipe */ + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + log.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]); + } else { + if (*fno_stdout == STDOUT_FILENO) fno_stdout = NULL; + else fsync(*fno_stdout); + } + } + + /* Setup child's stderr */ + if (fno_stderr) { + if (*fno_stderr < 0) { + /* Caller requests a pipe by specifying descriptor -1 */ + rc = pipe(pipe_err); + if (rc) { + /* error creating pipe */ + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + log.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]); + } else { + if (*fno_stderr == STDERR_FILENO) fno_stderr = NULL; + else fsync(*fno_stderr); + } + } + + /* fork a child process to run the command in */ + log.Debug("popen: forking now"); + pid = fork(); + switch (pid) + { + case -1: /* error creating process */ + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + + case 0: /* child is running */ + /* close pipe ends always used by parent */ + log.Debug("popen: child closing pipe ends %d,%d,%d used by parent", pipe_in[1], pipe_out[0], pipe_err[0]); + if (pipe_in[1] >= 0) close(pipe_in[1]); + if (pipe_out[0] >= 0) close(pipe_out[0]); + if (pipe_err[0] >= 0) close(pipe_err[0]); + /* assign child's stdin */ + if (fno_stdin) { + if (*fno_stdin < 0) { + /* Read end of pipe will be child's stdin */ + log.Debug("popen: child will read stdin from %d", pipe_in[0]); + dup2(pipe_in[0], STDIN_FILENO); + close(pipe_in[0]); + } else { + /* Child's stdin will read from caller's input file */ + dup2(*fno_stdin, STDIN_FILENO); + close(*fno_stdin); + } + } + /* assign child's stdout */ + if (fno_stdout) { + if (*fno_stdout < 0) { + /* Write end of pipe will be child's stdout */ + log.Debug("popen: child will write stdout to %d", pipe_out[1]); + dup2(pipe_out[1], STDOUT_FILENO); + close(pipe_out[1]); + } else { + /* Child's stdout will write to caller's output file */ + dup2(*fno_stdout, STDOUT_FILENO); + close(*fno_stdout); + } + } + /* assign child's stderr */ + if (fno_stderr) { + if (*fno_stderr < 0) { + /* Write end of pipe will be child's stderr */ + log.Debug("popen: child will write stderr to %d", pipe_err[1]); + dup2(pipe_err[1], STDERR_FILENO); + close(pipe_err[1]); + } else { + /* Child's stderr will write to caller's error file */ + dup2(*fno_stderr, STDERR_FILENO); + close(*fno_stderr); + } + } + /* now run the command */ + log.Debug("popen: child executing '%s'", argv[0]); + execvp(argv[0], argv); + /* only gets here if execvp fails */ + return -1; + } + + /* parent is running this */ + + /* close pipe ends always used by child */ + log.Debug("popen: parent closing pipe ends %d,%d,%d used by child", pipe_in[0], pipe_out[1], pipe_err[1]); + if (pipe_in[0] >= 0) close(pipe_in[0]); + if (pipe_out[1] >= 0) close(pipe_out[1]); + if (pipe_err[1] >= 0) close(pipe_err[1]); + + /* Pass pipe ends being used back to caller */ + if (fno_stdin) { + if (*fno_stdin < 0) { + /* Caller will be writing to child's stdin through pipe */ + *fno_stdin = pipe_in[1]; + log.Debug("popen: parent writes child's stdin to %d", pipe_in[1]); + } + } + if (fno_stdout) { + if (*fno_stdout < 0) { + /* Caller will be reading from child's stdout through pipe */ + *fno_stdout = pipe_out[0]; + log.Debug("popen: parent reads child's stdout from %d", pipe_out[0]); + } + } + if (fno_stderr) { + if (*fno_stderr < 0) { + /* Caller will be reading from child's stderr through pipe */ + *fno_stderr = pipe_err[0]; + log.Debug("popen: parent reads child's stderr from %d", pipe_err[0]); + } + } + //sleep(2); + log.Debug("popen: parent returning pid=%d of child", pid); + return pid; +} + +#else +static int do_mypopen_raw(const char *cline, int *fno_stdin, int *fno_stdout, int *fno_stderr) +{ + int rc, pipe_in[2], pipe_out[2], pipe_err[2]; + int save_in = -1, save_out = -1, save_err = -1; + int child_in = -1, child_out = -1, child_err = -1; + int n, pid = -1, argc = 50; + char *argv[50], argbuf[4096]; + + /* Sanity check parameters */ + if (!cline || !cline[0]) { + errno = EINVAL; + return -1; + } + for (n = 0; n < 2; n++) + { + pipe_in[n] = -1; + pipe_out[n] = -1; + pipe_err[n] = -1; + } + + /* Build argv array from command line string */ + if (mypopen_args(cline, argv, argc, argbuf, sizeof(argbuf))) { + /* Invalid args, so terminate child */ + log.Debug("popen: invalid cmdline args for child"); + errno = EINVAL; + return -1; + } + + /* Determine child's stdin */ + if (fno_stdin) { + if (*fno_stdin < 0) { + /* Caller requests a pipe for writing to child's stdin */ + rc = _pipe(pipe_in, 4096, O_NOINHERIT); + if (rc) { + /* error creating pipe */ + return -1; + } + child_in = pipe_in[0]; + log.Debug("popen: child stdin uses pipe (%d -> %d)", pipe_in[0], pipe_in[1]); + } else { + if (*fno_stdin != STDIN_FILENO) { + /* Caller supplied an open file to use as child's stdin */ + child_in = *fno_stdin; + } + } + } + + /* Determine child's stdout */ + if (fno_stdout) { + if (*fno_stdout < 0) { + /* Caller requests a pipe for reading from child's stdout */ + rc = _pipe(pipe_out, 4096, O_NOINHERIT); + if (rc) { + /* error creating pipe */ + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + child_out = pipe_out[1]; + log.Debug("popen: child stdout uses pipe (%d -> %d)", pipe_out[0], pipe_out[1]); + } else { + if (*fno_stdout != STDOUT_FILENO) { + /* Caller supplied open file to use as child's stdout */ + child_out = *fno_stdout; + } + } + } + + /* Setup child's stderr */ + if (fno_stderr) { + if (*fno_stderr < 0) { + /* Caller requests a pipe for reading from child's stderr */ + rc = _pipe(pipe_err, 5096, O_NOINHERIT); + if (rc) { + /* error creating pipe */ + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + child_err = pipe_err[1]; + log.Debug("popen: child stderr uses pipe (%d -> %d)", pipe_err[0], pipe_err[1]); + } else { + if (*fno_stderr != STDERR_FILENO) { + /* Caller supplied an open file to use as child's stderr */ + child_err = *fno_stderr; + } + } + } + + /* Save original stdin and make stdin a duplicate of file child is to use */ + if (child_in >= 0) { + save_in = _dup(STDIN_FILENO); + if (save_in < 0) { + rc = errno; + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + if(_dup2(child_in, STDIN_FILENO) != 0) { + rc = errno; + close(save_in); + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + } + + /* Save original stdout and make stdout a duplicate of file child is to use */ + if (child_out >= 0) { + save_out = _dup(STDOUT_FILENO); + if (save_out < 0) { + rc = errno; + if (save_in >= 0) { + _dup2(save_in, STDIN_FILENO); + close(save_in); + pipe_in[0] = -1; + } + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + if(_dup2(child_out, STDOUT_FILENO) != 0) { + rc = errno; + close(save_out); + if (save_in >= 0) { + _dup2(save_in, STDIN_FILENO); + close(save_in); + pipe_in[0] = -1; + } + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + } + + /* Save original stderr and make stderr a duplicate of file child is to use */ + if (child_err >= 0) { + save_err = _dup(STDERR_FILENO); + if (save_err < 0) { + rc = errno; + if (save_in >= 0) { + _dup2(save_in, STDIN_FILENO); + close(save_in); + pipe_in[0] = -1; + } + if (save_out >= 0) { + _dup2(save_out, STDOUT_FILENO); + close(save_out); + pipe_out[1] = -1; + } + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + if(_dup2(child_err, STDERR_FILENO) != 0) { + rc = errno; + close(save_out); + if (save_in >= 0) { + _dup2(save_in, STDIN_FILENO); + close(save_in); + pipe_in[0] = -1; + } + if (save_out >= 0) { + _dup2(save_out, STDOUT_FILENO); + close(save_out); + pipe_out[1] = -1; + } + CloseAllPipes(pipe_in, pipe_out, pipe_err); + errno = rc; + return -1; + } + } + + /* Spawn the child process */ + rc = 0; + pid = _spawnvp(_P_NOWAIT, argv[0], argv); + if (pid < 0) { + /* spawn failed */ + rc = errno; + } + + /* Restore parent's stdin, stdout, and stderr */ + if (save_in >= 0) { + _dup2(save_in, STDIN_FILENO); + close(save_in); + pipe_in[0] = -1; + } + if (save_out >= 0) { + _dup2(save_out, STDOUT_FILENO); + close(save_out); + pipe_out[1] = -1; + } + if (save_err >= 0) { + _dup2(save_err, STDERR_FILENO); + close(save_err); + pipe_err[1] = -1; + } + + if (rc) { + CloseAllPipes(pipe_in, pipe_out, pipe_err); + return -1; + } + + /* Pass requested pipe ends back to caller */ + if (pipe_in[1] >= 0) *fno_stdin = pipe_in[1]; + if (pipe_out[0] >= 0) *fno_stdout = pipe_out[0]; + if (pipe_err[0] >= 0) *fno_stderr = pipe_err[0]; + + log.Debug("popen: parent returning pid=%d of child", pid); + return pid; +} + +#endif + +/* + * Function to fork a child process, specifying the command and arguments to be + * run in the child and the child's standard i/o files. If fno_stdXXX is NULL, + * then the child will inherit the parent's stdXXX. If *fno_stdXXX is -1, then + * a pipe will be created with the child's stdXXX being one end of the pipe and + * the other end of the pipe being passed back to the caller in *fno_stdXXX. If + * *fno_stdXXX zero or greater, then it specifies a file descriptor that will be + * used as stdXXX in the child. + * On success, returns the pid of the child. On error, returns -1 and sets errno. + */ +int mypopen_raw(const char *command, int *fno_stdin, int *fno_stdout, int *fno_stderr) +{ + return do_mypopen_raw(command, fno_stdin, fno_stdout, fno_stderr); +} + + +/* + * Function to fork a child process, specifying the command to be run in the child + * and acquiring open file streams to the child's stdXXX files. If any of fs_XXX are + * NULL, then the child will inherit the parent's corresponding stdXXX. If fs_XXX points + * to an open file stream, then the child will use that file as its stdXXX. If fs_XXX + * points to NULL, then on return *fs_XXX will be an open file connected by a pipe to + * the child's corresponding stdXXX. + * On success, returns the pid of the child process. On error, returns -1 and + * sets errno appropriately. + */ +int mypopen(const char *cmd, FILE **fs_in, FILE **fs_out, FILE **fs_err) +{ + int pid, fno_in = -1, fno_out = -1, fno_err = -1; + int *in_p = NULL, *out_p = NULL, *err_p = NULL; + if (fs_in) { + in_p = &fno_in; + if (*fs_in) { + fno_in = fileno(*fs_in); + if (fno_in == STDIN_FILENO) { + in_p = NULL; + fs_in = NULL; + } + } + } + if (fs_out) { + out_p = &fno_out; + if (*fs_out) { + fno_out = fileno(*fs_out); + if (fno_out == STDOUT_FILENO) { + out_p = NULL; + fs_out = NULL; + } + } + } + if (fs_err) { + err_p = &fno_err; + if (*fs_err) { + fno_err = fileno(*fs_err); + if (fno_err == STDERR_FILENO) { + err_p = NULL; + fs_err = NULL; + } + } + } + pid = do_mypopen_raw(cmd, in_p, out_p, err_p); + if (pid < 0) return -1; + if (fs_in && *fs_in == NULL) *fs_in = fdopen(fno_in, "w"); + if (fs_out && *fs_out == NULL) *fs_out = fdopen(fno_out, "r"); + if (fs_err && *fs_err == NULL) *fs_err = fdopen(fno_err, "r"); + return pid; +} + + +/* + * Function to fork a child process, specifying the command to be run in the child + * and files the child will use for stdXXX. If cmd_XXX is non-null, then it specifies + * the name of a file that the child is to use as its stdXXX. If the filename is empty + * then "/dev/null" is used. If cmd_XXX is NULL, then the child will use the caller's stdXXX. + * On success, returns the result code from the command. On error, returns -1 and + * sets errno appropriately. + */ +int mypopenrw(const char *command, const char *cmd_in, const char *cmd_out, const char *cmd_err) +{ + int pid, rc, st; + int fno_in = -1, fno_out = -1, fno_err = -1; + int *fno_in_p = NULL, *fno_out_p = NULL, *fno_err_p = NULL; + + /* Execute command in a child process, setting child's stdin, stdout, and stderr */ + if (cmd_in) { + if (cmd_in[0]) fno_in = open(cmd_in, O_RDONLY); + else fno_in = open("/dev/null", O_RDONLY); + if (fno_in < 0) return -1; + fno_in_p = &fno_in; + } + if (cmd_out) { + if (cmd_out[0]) { +#ifndef HAVE_WINDOWS_H + fno_out = open(cmd_out, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP); +#else + fno_out = _open(cmd_out, O_WRONLY|O_CREAT, _S_IWRITE); +#endif + } else fno_out = open("/dev/null", O_WRONLY); + if (fno_out < 0) { + rc = errno; + if (fno_in >= 0) close(fno_in); + errno = rc; + return -1; + } + fno_out_p = &fno_out; + } + if (cmd_err) { + if (cmd_err[0]) { +#ifndef HAVE_WINDOWS_H + fno_err = open(cmd_err, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP); +#else + fno_err = _open(cmd_err, O_WRONLY|O_CREAT, _S_IWRITE); +#endif + } else fno_err = open("/dev/null", O_WRONLY); + if (fno_err < 0) { + rc = errno; + if (fno_in >= 0) close(fno_in); + if (fno_out >= 0) close(fno_out); + errno = rc; + return -1; + } + fno_err_p = &fno_err; + } + pid = do_mypopen_raw(command, fno_in_p, fno_out_p, fno_err_p); + if (pid < 0) { + /* Command execution failed */ + if (fno_in >= 0) close(fno_in); + if (fno_out >= 0) close(fno_out); + if (fno_err >= 0) close(fno_err); + return -1; + } + /* Wait for child process to exit */ +#ifndef HAVE_WINDOWS_H + rc = waitpid(pid, &st, 0); + while (rc < 0) { + if (errno != EINTR) { + if (fno_in >= 0) close(fno_in); + if (fno_out >= 0) close(fno_out); + if (fno_err >= 0) close(fno_err); + return -1; + } + rc = waitpid(pid, &st, 0); + } + /* get child's result code */ + if (!WIFEXITED(st)) { + /* Command was killed for some reason */ + return -1; + } + rc = WEXITSTATUS(st); + +#else + if (_cwait(&rc, pid, WAIT_CHILD) != pid) { + if (fno_in >= 0) close(fno_in); + if (fno_out >= 0) close(fno_out); + if (fno_err >= 0) close(fno_err); + return -1; + } +#endif + + if (fno_in >= 0) { + close(fno_in); + } + if (fno_out >= 0) { + close(fno_out); + } + if (fno_err >= 0) { + close(fno_err); + } + return rc; +} + diff --git a/src/mypopen.h b/src/mypopen.h new file mode 100644 index 0000000..157e286 --- /dev/null +++ b/src/mypopen.h @@ -0,0 +1,37 @@ +/* mypopen.h + * + * Copyright (C) 2013-2014 Josh Fisher + * + * This program is free software. You may 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, 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. See the file "COPYING". If not, + * see . +*/ + +#ifndef _MYPOPEN_H_ +#define _MYPOPEN_H_ 1 + +#include "tstring.h" + +int mypopen_raw(const char *command, int *fno_stdin, int *fno_stdout, int *fno_stderr); +inline int mypopen_raw(const tString &command, int *fno_stdin, int *fno_stdout, int *fno_stderr) + { return mypopen_raw(command.c_str(), fno_stdin, fno_stdout, fno_stderr); } +int mypopen(const char *command, FILE **cmd_stdin = NULL, FILE **cmd_stdout = NULL, + FILE **cmd_stderr = NULL); +inline int mypopen(const tString &command, FILE **cmd_stdin = NULL, FILE **cmd_stdout = NULL, + FILE **cmd_stderr = NULL) + { return mypopen(command.c_str(), cmd_stdin, cmd_stdout, cmd_stderr); } +int mypopenrw(const char *command, const char *cmd_in = NULL, const char *cmd_out = NULL, const char *cmd_err = NULL); +inline int mypopenrw(const tString &command, const char *cmd_in = NULL, const char *cmd_out = NULL, const char *cmd_err = NULL) + { return mypopenrw(command.c_str(), cmd_in, cmd_out, cmd_err); } + +#endif /* _MYPOPEN_H_ */ diff --git a/src/targetver.h b/src/targetver.h new file mode 100644 index 0000000..c9d5562 --- /dev/null +++ b/src/targetver.h @@ -0,0 +1,24 @@ + +/* The following macros define the minimum required platform. The minimum required platform + * is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run + * your application. The macros work by enabling all features available on platform versions up to and + * including the version specified. + * + * Modify the following defines if you have to target a platform prior to the ones specified below. + * Refer to MSDN for the latest info on corresponding values for different platforms. + */ +#ifndef _TARGETVER_H_ +#define _TARGETVER_H_ 1 +#ifdef HAVE_WINDOWS_H +#ifndef WINVER +#define WINVER 0x0600 +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#ifndef _WIN32_IE +#define _WIN32_IE 0x0700 +#endif +#define _POSIX 1 +#endif +#endif diff --git a/src/tstring.cpp b/src/tstring.cpp new file mode 100644 index 0000000..67c0dda --- /dev/null +++ b/src/tstring.cpp @@ -0,0 +1,476 @@ +/* tstring.cpp + * + * This file is part of the msafe package by Josh Fisher. + * + * vchanger copyright (C) 2006-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License, version 2, as published by the Free + * Software Foundation + * + * vchanger 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 msafe. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "config.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#include "tstring.h" + + + +/* + * Function to make string lower case + */ +tString& tToLower(tString &b) +{ + tStringIterator p; + for (p = b.begin(); p != b.end(); p++) { + *p = tolower(*p); + } + return b; +} + +tString tToLower(const char *sin) +{ + tString b(sin); + tToLower(b); + return b; +} + +/* + * Function to make string upper case + */ +tString& tToUpper(tString &b) +{ + tStringIterator p; + for (p = b.begin(); p != b.end(); p++) { + *p = toupper(*p); + } + return b; +} + +tString tToUpper(const char *sin) +{ + tString b(sin); + tToUpper(b); + return b; +} + +/* + * Function to strip leading whitespace + */ +tString& tStripLeft(tString &b) +{ + tStringIterator p; + for (p = b.begin(); p != b.end() && isblank(*p); p++) ; + if (p != b.begin()) { + b.erase(b.begin(), p); + } + return b; +} + +tString tStripLeft(const char *sin) +{ + tString b(sin); + tStripLeft(b); + return b; +} + +/* + * Function to strip trailing blanks + */ +tString& tStripRight(tString &b) +{ + tStringIterator p = b.begin(); + size_t n = b.find_last_not_of(" \t"); + if (n != tString::npos) p += (n + 1); + b.erase(p, b.end()); + return b; +} + +tString tStripRight(const char *sin) +{ + tString b(sin); + tStripRight(b); + return b; +} + +/* + * Function to strip leading and trailing whitespace + */ +tString& tStrip(tString &b) +{ + return tStripLeft(tStripRight(b)); +} + +tString tStrip(const char *sin) +{ + tString b(sin); + tStrip(b); + return b; +} + +/* + * Function to remove all SP and HTAB chars from b + */ +tString& tRemoveWS(tString &b) +{ + size_t n = b.find_first_of(" \t"); + while (n != tString::npos) { + b.erase(n, 1); + n = b.find_first_of(" \t", n); + } + return b; +} + +tString tRemoveWS(const char *sin) +{ + tString b(sin); + tRemoveWS(b); + return b; +} + +/* + * Function to remove trailing line ending + */ +tString& tRemoveEOL(tString &b) +{ + if (b.empty() || b[b.size() - 1] != '\n') return b; + b.erase(b.end() - 1); + if (!b.empty() && b[b.size() - 1] == '\r') b.erase(b.end() - 1); + return b; +} + +tString tRemoveEOL(const char *sin) +{ + tString b(sin); + tRemoveEOL(b); + return b; +} + +/* + * Function to change LF endings to CRLF + */ +tString& tLF2CRLF(tString &b) +{ + size_t n = b.find_first_of('\n'); + while (n != tString::npos) { + if (n && b[n-1] != '\r') { + b.insert(n, 1, '\r'); + n += 2; + } else ++n; + n = b.find_first_of('\n', n); + } + return b; +} + +tString tLF2CRLF(const char *sin) +{ + tString b(sin); + tLF2CRLF(b); + return b; +} + +/* + * Function to change CRLF endings to LF + */ +tString& tCRLF2LF(tString &b) +{ + size_t n = b.find("\r\n"); + while (n != tString::npos) { + b.erase(n, 1); + n = b.find("\r\n", n); + } + return b; +} + +tString tCRLF2LF(const char *sin) +{ + tString b(sin); + tCRLF2LF(b); + return b; +} + +/* + * Function to extract the next line of text from sin + * Returns line extracted. + */ +tString tExtractLine(const tString &b, size_t &pos) +{ + size_t p1 = pos; + pos = b.find('\n', pos); + if (pos == tString::npos) pos = b.size(); + else ++pos; + return b.substr(p1, pos - p1); +} + +tString tExtractLine(const char *sin, size_t &pos) +{ + tString b(sin); + return tExtractLine(b, pos); +} + +/* + * Function to compare two case-insensitive strings as in C function strcasecmp() + */ +int tCaseCmp(const char *a, const char *b) +{ + if (!a || !a[0]) return b && b[0] ? -1 : 0; + if (!b || !b[0]) return 1; + return strcasecmp(a, b); +} + +/* + * Function to do case-insensitive search for character b from position pos + * in string a + */ +size_t tCaseFind(const tString &a, char b, size_t pos) +{ + b = tolower(b); + tString str = a; + tToLower(str); + return str.find(b, pos); +} + +/* + * Function to do case-insensitive search for C string b from position pos + * in string a + */ +size_t tCaseFind(const tString &a, const char *b_in, size_t pos) +{ + tString str(a), b(b_in); + tToLower(str); + tToLower(b); + return str.find(b, pos); +} + +/* + * Function to get line of text from a file stream + */ +const char* tGetLine(tString &str, FILE *FS) +{ + char buf[4096]; + if (fgets(buf, sizeof(buf), FS) == NULL) { + str.clear(); + return NULL; + } + str = buf; + return str.c_str(); +} + +/* + * Function to format a string using sprintf + */ +const char* tFormat(tString &str, const char *fmt, ...) +{ + char buf[8192]; + va_list vl; + va_start(vl, fmt); + vsnprintf(buf, sizeof(buf), fmt, vl); + va_end(vl); + buf[8191] = 0; + str = buf; + return str.c_str(); +} + +/* + * Function to parse next token from position 'pos' in string 'str'. + * The text determining the token is placed in 'word'. 'pos' is + * updated to reference the character following the token text, or + * end of string if no characters follow the token text. + * Returns: + * 0 Past end of string + * 'A' Atom was found + * ' ' Whitespace was found + * '\n' EOL char sequence was found + * Special char was found + */ +char tParseStandard(tString &word, const char *str, size_t &pos, tString special, tString ws) +{ + size_t n, slen; + if (ws.empty()) ws = " \t"; + word.clear(); + if (!str || !str[0]) return 0; + slen = strlen(str); + if (pos >= slen) { + pos = slen; + return 0; + } + if (ws.find(str[pos]) != tString::npos) { + /* Extract whitespace sequence */ + for (n = pos; n < slen && ws.find(str[n]) != tString::npos; n++) ; + word.insert(0, str + pos, n - pos); + pos = n; + return ' '; + } + if (special.find(str[pos]) != tString::npos) { + /* Extract special character */ + word = str[pos++]; + return word[0]; + } + if (str[pos] == '\r') { + /* Extract CR or CRLF line ending */ + word = '\r'; + ++pos; + if (str[pos] == '\n') { + word += '\n'; + ++pos; + } + return '\n'; + } + if (str[pos] == '\n') { + /* Extract LF line ending */ + word = '\n'; + ++pos; + return '\n'; + } + /* Extract atom */ + for (n = pos; n < slen && str[n] != '\r' && str[n] != '\n' && ws.find(str[n]) == tString::npos + && special.find(str[n]) == tString::npos; n++) ; + word.insert(0, str + pos, n - pos); + pos = n; + return 'A'; +} + + +/* + * Function to parse next value in comma-separated-value string 'str' + * on or after position 'pos' and store the value in 'word'. The value + * returned in 'word' will have quoting and escape sequences decoded. + * 'pos' is updated and set to the position in 'str' of the character + * following the next delimiter (',') or end of line/string if there are + * no more delimiters. + * Returns: + * -1 Missing closing quote + * 0 Past end of string + * 1 Found column field + * 2 Found line ending + */ +int tParseCSV(tString &word, const char *str, size_t &pos) +{ + size_t p, slen = strlen(str); + char c; + tString w; + + word.clear(); + c = tParseStandard(w, str, pos, "\","); + if (!c) return 0; /* At end of string */ + if (c == '\n') { + /* EOL found */ + word = w; + return 2; + } + /* Skip leading whitespace */ + while (c == ' ') c = tParseStandard(w, str, pos, "\","); + if (c == 0) { + /* Found empty field terminated by end of string */ + return 0; + } + if (c == '\n') { + /* Found empty field terminated by EOL */ + word = w; + return 2; + } + /* extract field */ + while (c && c != '\n' && c != ',') { + if (c == '"') { + /* Extracting quoted string */ + c = tParseStandard(w, str, pos, "\"\\"); + while (c && c != '"') { + if (c == '\\') { + switch (str[pos]) { + case 0: + return -1; + case 'r': + word += '\r'; + break; + case 'n': + word += '\n'; + break; + case 't': + word += '\t'; + break; + case 'v': + word += '\v'; + break; + case 'b': + word += '\b'; + break; + case 'a': + word += '\a'; + break; + case 'x': + /* Process hex escape sequence */ + if (isxdigit(str[pos + 1])) { + ++pos; + w.clear(); + for (p = 0; pos < slen && p < 2 && isxdigit(str[pos]); p++) { + w += str[pos++]; + } + word += (char)strtoul(w.c_str(), NULL, 16); + --pos; + } else word += 'x'; + break; + default: + if (str[pos] >= '0' && str[pos] <= '7') { + /* Process octal escape sequence */ + w.clear(); + for (p = 0; pos < slen && p < 3 && str[pos] >= '0' && str[pos] <= '7'; p++) { + w += str[pos++]; + } + word += (char)strtoul(w.c_str(), NULL, 8); + --pos; + } else { + /* anything else following an escape is a literal */ + word += str[pos]; + } + } + ++pos; + } else { + word += w; + } + } + if (c != '"') { + /* Closing '"' not found */ + return -1; + } + } else if (c == ' ' || c == '\n') { + /* Extracting unquoted whitespace. Replace with single SP */ + if (c == ' ') word += ' '; + } + else { + /* Extracting atom or special char */ + word += w; + } + c = tParseStandard(w, str, pos, "\","); + } + /* Found a field */ + if (c == '\n') { + /* If line ending terminated field, put it back */ + pos -= w.size(); + } + return 1; +} diff --git a/src/tstring.h b/src/tstring.h new file mode 100644 index 0000000..3e2d748 --- /dev/null +++ b/src/tstring.h @@ -0,0 +1,80 @@ +/* tstring.h + * + * This file is part of msafe by Josh Fisher. + * + * vchanger copyright (C) 2006-2014 Josh Fisher + * + * vchanger is free software. + * You may 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, or (at your option) any later version. + * + * vchanger 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 msafe. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _TSTRING_H_ +#define _TSTRING_H_ + +#include +#include +#include +#include + +typedef std::basic_string tString; +typedef tString::iterator tStringIterator; +typedef tString::const_iterator tStringConstIterator; +typedef tString::reverse_iterator tStringReverseIterator; +typedef tString::const_reverse_iterator tStringConstReverseIterator; +typedef std::list tStringList; +typedef tStringList::iterator tStringListIterator; +typedef tStringList::const_iterator tStringListConstIterator; +typedef tStringList::reverse_iterator tStringListReverseIterator; +typedef tStringList::const_reverse_iterator tStringListConstReverseIterator; +typedef std::vector tStringArray; +typedef std::map tStringMap; +typedef std::map tStringListMap; + +tString& tToLower(tString &b); +tString tToLower(const char *sin); +tString& tToUpper(tString &b); +tString tToUpper(const char *sin); +tString& tStripLeft(tString &b); +tString tStripLeft(const char *sin); +tString& tStripRight(tString &b); +tString tStripRight(const char *sin); +tString& tStrip(tString &b); +tString tStrip(const char *sin); +tString& tRemoveWS(tString &b); +tString tRemoveWS(const char *b); +tString& tRemoveEOL(tString &b); +tString tRemoveEOL(const char *sin); +tString& tLF2CRLF(tString &b); +tString tLF2CRLF(const char *sin); +tString& tCRLF2LF(tString &b); +tString tCRLF2LF(const char *sin); +tString tExtractLine(const tString &b, size_t &pos); +tString tExtractLine(const char *sin, size_t &pos); +size_t tCaseFind(const tString &str, char c, size_t pos = 0); +size_t tCaseFind(const tString &str, const char *pat, size_t pos = 0); +inline size_t tCaseFind(const tString &str, const tString &pat, size_t pos = 0) + { return tCaseFind(str, pat.c_str(), pos); } +int tCaseCmp(const char *a, const char *b); +inline int tCaseCmp(const tString &a, const char *b) { return tCaseCmp(a.c_str(), b); } +inline int tCaseCmp(const char *a, const tString &b) { return tCaseCmp(a, b.c_str()); } +inline int tCaseCmp(const tString &a, const tString &b) { return tCaseCmp(a.c_str(), b.c_str()); } +const char* tGetLine(tString &str, FILE *FS); +const char* tFormat(tString &str, const char *fmt, ...); +char tParseStandard(tString &word, const char *str, size_t &pos, tString special = "", tString ws = ""); +int tParseCSV(tString &word, const char *str, size_t &pos); +inline int tParseCSV(tString &word, const tString &str, size_t &pos) + { return tParseCSV(word, str.c_str(), pos); } + +#endif diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..e345106 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,192 @@ +/* util.cpp + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * This file simply provides some utility functions + */ + +#include "config.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STDARG_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include "util.h" + +/*------------------------------------------------- + * Function to return elapsed time between two struct timeval values + * in microseconds. + *------------------------------------------------*/ +long timeval_et(struct timeval *tv1, struct timeval *tv2) +{ + if (!tv1 || !tv2) return 0; + return ((tv2->tv_sec - tv1->tv_sec) * 1000000) + tv2->tv_usec - tv1->tv_usec; +} + + +/*------------------------------------------------- + * Function to open file 'fname' for write in exclusive access mode. + * On success, returns the opened stream. Otherwise, on error returns + * NULL. + *------------------------------------------------*/ +int exclusive_fopen(const char *fname, FILE **fs) +{ + int fd, result = 0; + *fs = NULL; + fd = open(fname, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); + if (fd > 0) { + *fs = fdopen(fd, "w"); + if (*fs == NULL) { + result = errno; + close(fd); + unlink(fname); + } + } else { + result = errno; + } + return result; +} + + +/*------------------------------------------------- + * Function to copy file 'from_path' to new file 'to_path'. + * On success returns zero, else returns errno + *------------------------------------------------*/ +int file_copy(const char *to_path, const char *from_path) +{ + int rc; + size_t n; + FILE *to, *from; + char *buf; + size_t buf_sz = 1024 * 1024; + + if (access(to_path, F_OK) == 0) return EEXIST; + from = fopen(from_path, "r"); + if (!from) return errno; + to = fopen(to_path, "w"); + if (!to) { + rc = errno; + fclose(from); + return rc; + } + buf = (char*)malloc(buf_sz); + while ((n = fread(buf, 1, buf_sz, from)) > 0) { + if (fwrite(buf, 1 , n, to) != n) { + rc = ferror(to); + fclose(to); + unlink(to_path); + fclose(from); + free(buf); + return rc; + } + } + free(buf); + fclose(to); + if (!feof(from)) { + rc = ferror(from); + unlink(to_path); + fclose(from); + return rc; + } + fclose(from); + return 0; +} + +/*------------------------------------------------- + * Function to drop root privileges and change persona to uid:gid + * of the given user name and group name. + * On success returns zero, else on error returns errno. + *------------------------------------------------*/ +int drop_privs(const char *uname, const char *gname) +{ +#ifdef HAVE_WINDOWS_H + return 0; /* For windows ignore user switching */ +#else + gid_t new_gid; + struct passwd *pw; + struct group *gr; + if (!uname || !uname[0] || getuid()) return 0; /* Nothing to do */ + if ((pw = getpwnam(uname)) == NULL) return errno; + if (pw->pw_uid == 0) return 0; /* already running as root */ + new_gid = pw->pw_gid; + if (gname && gname[0]) { + /* find given group */ + if ((gr = getgrnam(gname)) == NULL) return errno; /* no such group */ + new_gid = gr->gr_gid; + } + /* Set supplemental groups */ + if (initgroups(uname, new_gid)) return errno; + /* Start running as given group */ + if (setgid(new_gid)) return errno; + /* Drop root and run as given user */ + if (setuid(pw->pw_uid)) return errno; + return 0; +#endif +} + + +/*------------------------------------------------- + * Function returns zero if current user not superuser + * else non-zero. + *------------------------------------------------*/ +int is_root_user() +{ +#ifndef HAVE_WINDOWS_H + return getuid() == 0 ? 1 : 0; +#endif + return 0; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..be86752 --- /dev/null +++ b/src/util.h @@ -0,0 +1,33 @@ +/* util.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _UTIL_H_ +#define _UTIL_H_ 1 + +/* Utility Functions */ +long timeval_et(struct timeval *tv1, struct timeval *tv2); +int exclusive_fopen(const char *fname, FILE **fs); +int file_copy(const char *to, const char *from); +int drop_privs(const char *uname, const char *gname); +int is_root_user(); + +#endif /* _UTIL_H_ */ diff --git a/src/uuidlookup.c b/src/uuidlookup.c new file mode 100644 index 0000000..3e79f67 --- /dev/null +++ b/src/uuidlookup.c @@ -0,0 +1,364 @@ +/* uuidlookup.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif + +#include "uuidlookup.h" + +#ifdef HAVE_WINDOWS_H + +#include "targetver.h" +#include +#include +#include "win32_util.h" + +/* + * Locates disk partition containing file system with volume serial number + * given by 'uuid_str'. If found, and the filesystem is mounted, returns the + * first mountpoint found in 'mountp'. On success, returns zero. On error, + * returns negative value : + * -1 system error + * -2 parameter error + * -3 volume with given uuid not found + * -4 'mountp' buffer too small + */ +int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str) +{ + HANDLE hnd, hFile; + wchar_t volname[2048]; + wchar_t pname[2048]; + char tmp[128], *utf8name = NULL; + BOOL rc; + DWORD volser, count, eov, uuid; + size_t n; + + /* Convert uuid_str to binary. Note that win32 volume serial number is not + * in standard UUID format, but is the form xxxx-xxxx, where x is a hex digit. + * Win32 returns volume serial number as 32-bit unsigned binary. + */ + mountp[0] = '\0'; + strncpy(tmp, uuid_str, sizeof(tmp)); + if (strlen(uuid_str) != 9 || tmp[4] != '-') { + /* invalid volume serial number */ + return -2; + } + for (n = 4; n < 9; n++) { + tmp[n] = tmp[n+1]; + } + uuid = strtoul(tmp, NULL, 16); + + /* Enumerate volumes on this system looking for matching volume serial number. + * Skip unmounted volumes. + */ + hnd = FindFirstVolumeW(volname, 2048); + if (hnd == INVALID_HANDLE_VALUE) { + /* out of memory?? permissions problem?? */ + return -1; + } + rc = TRUE; + while (rc) { + /* make sure it's a proper volume name */ + if (volname[0] == L'\\' && volname[1] == L'\\' && volname[2] == L'?' + && volname[3] == L'\\' && volname[eov] == L'\\') { + /* Get volume's first mountpoint */ + if (GetVolumePathNamesForVolumeNameW(volname, pname, 2048, &count)) { + /* retrieve serial from volume information */ + if (GetVolumeInformationW(pname, NULL, 0, &volser, NULL, NULL, NULL, 0)) { + /* see if this volume matches requested UUID */ + if (volser == uuid) { + /* found matching volume. UTF16 mountpoint path is in pname. */ + break; + } + } + } + } + /* get next volume name */ + rc = FindNextVolumeW(hnd, volname, 2048); + } + FindVolumeClose(hnd); + if (!rc) { + return -3; /* volume not found */ + } + + /* Convert UTF16 mountpoint path to UTF8 */ + UTF16ToAnsi(pname, &utf8name, &n); + if (n > mountp_sz) { + free(utf8name); + return -4; /* mountp buffer too small */ + } + strncpy(mountp, utf8name, mountp_sz); + free(utf8name); + return 0; +} + +#else + +#ifdef HAVE_MNTENT_H +#include + +/* + * Lookup mount point for device 'devname' and place in 'mountp' + * using SunOS 4.1.3+ function getmntent(). + * On success, returns zero. On error, returns negative value : + * -1 system error + * -2 parameter error + * -4 devname not mounted + * -5 mountp buffer too small + */ +static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname) +{ + size_t n; + FILE *fs; + struct mntent *ent; + int rc; + + mountp[0] = '\0'; + if (!mountp_sz || !devname || !strlen(devname)) return -2; + + /* Read either /proc/mounts or /etc/mtab depending on build system's glibc */ + fs = setmntent(_PATH_MOUNTED, "r"); + if (fs == NULL) return -1; /* unknown non-POSIX system?? */ + + rc = -4; + ent = getmntent(fs); + while (ent) + { + if (strcasecmp(devname, ent->mnt_fsname) == 0) { + n = strlen(ent->mnt_dir); + if (n >= mountp_sz) { + rc = -5; + break; + } + memmove(mountp, ent->mnt_dir, n); + mountp[n] = 0; + rc = 0; + break; + } + ent = getmntent(fs); + } + endmntent(fs); + return rc; +} + +#else + +#ifdef HAVE_GETFSSTAT + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif +#ifdef HAVE_SYS_UCRED_H +#include +#endif + +/* + * Lookup mount point for device 'devname' and place in 'mountp' + * using BSD4.4+ function getfsstat(). + * On success, returns zero. On error, returns negative value : + * -1 system error + * -2 parameter error + * -4 devname not mounted + */ +static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname) +{ + struct statfs *fs; + int mcount, fs_size, n, rc = -4; + + mountp[0] = '\0'; + if (!devname || !strlen(devname)) return -2; + mcount = getfsstat(NULL, 0, MNT_WAIT); + if (mcount < 1) return -1; + fs_size = (mcount + 1) * sizeof(struct statfs); + fs = (struct statfs*)malloc(fs_size); + if (!fs) return -1; + mcount = getfsstat(fs, fs_size, MNT_NOWAIT); + for (n = 0; n < mcount; n++) + { + if (strcasecmp(devname, fs[n].f_mntfromname) == 0) { + strncpy(mountp, fs[n].f_mntonname, mountp_sz); + rc = 0; + } + } + free(fs); + return rc; +} + +#else + +/* + * System has neither getmntent() nor getfsstat(). Return system error. + */ +static int GetDevMountpoint(char *mountp, size_t mountp_sz, const char *devname) +{ + return -1; +} + +#endif /* HAVE_GETFSSTAT */ +#endif /* HAVE_MNTENT_H */ + +#ifdef HAVE_LIBUDEV_H +#include + +/* + * Locates disk partition containing file system with UUID given by 'uuid_str'. + * If found, and the filesystem is mounted, returns the first mountpoint found in + * string 'mountp'. On success, returns zero. On error, returns negative value : + * -1 system error + * -2 parameter error + * -3 filesystem with given uuid not found + * -4 filesystem not mounted + * -5 mountp buffer too small + */ +int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + int rc = -3; + const char *dev_name, *path, *uuid; + size_t n, pos, dev_name_len; + char devlink[4096]; + + if (!mountp || !mountp_sz) return -2; + if (!uuid_str || !strlen(uuid_str)) return -2; + + /* Enumerate devices with a filesystem UUID property */ + udev = udev_new(); + if (!udev) return -1; + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_property(enumerate, "ID_FS_UUID", uuid_str); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + /* Find device with specified UUID */ + udev_list_entry_foreach(dev_list_entry, devices) { + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + uuid = udev_device_get_property_value(dev, "ID_FS_UUID"); + if (uuid && strcasecmp(uuid, uuid_str) == 0) { + /* Found device with this UUID, so get its kernel device node */ + dev_name = udev_device_get_property_value(dev, "DEVNAME"); + if (dev_name == NULL) { + /* Failed to get kernel device node */ + break; + } + /* Lookup mountpoint of the kernel device node */ + rc = GetDevMountpoint(mountp, mountp_sz, dev_name); + if (rc == 0) break; + /* If not mounted as the DEVNAME, also check if mounted as + * a device alias name from DEVLINKS */ + dev_name = udev_device_get_property_value(dev, "DEVLINKS"); + if (dev_name == NULL) { + /* Failed to get device alias links */ + break; + } + dev_name_len = strlen(dev_name); + pos = 0; + while (rc == -4 && pos < dev_name_len) { + for (n = pos; n < dev_name_len && !isblank(dev_name[n]); n++) ; + n -= pos; + memmove(devlink, dev_name + pos, n); + devlink[n] = 0; + rc = GetDevMountpoint(mountp, mountp_sz, devlink); + pos += n; + while (pos < dev_name_len && isblank(dev_name[pos])) ++pos; + } + break; + } + } + udev_enumerate_unref(enumerate); + udev_unref(udev); + return rc; +} + +#else + +#ifdef HAVE_BLKID_BLKID_H +#include + +/* + * Locates disk partition containing file system with UUID given by 'uuid_str'. + * If found, and the filesystem is mounted, returns the first mountpoint found in + * string 'mountp'. On success, returns zero. On error, returns negative value : + * -1 system error + * -2 parameter error + * -3 volume with given uuid not found + * -4 volume not mounted + * -5 mountp buffer too small + */ +int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str) +{ + int rc; + char *dev_name; + + if (!mountp || !mountp_sz) return -2; + if (!uuid_str || !strlen(uuid_str)) return -2; + + /* Get device with requested UUID from libblkid */ +#ifdef HAVE_BLKID_EVALUATE_TAG + dev_name = blkid_evaluate_tag("UUID", uuid_str, NULL); +#else + dev_name = blkid_get_devname(NULL, "UUID", uuid_str); +#endif + if (!dev_name) return -3; /* no device with UUID found */ + + /* find mount point for device */ + rc = GetDevMountpoint(mountp, mountp_sz, dev_name); + free(dev_name); + return rc; +} + +#else + +/* + * If built without libudev or libblkid support, then UUID lookup is a system error + */ +int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str) +{ + return -1; +} + +#endif /* HAVE_BLKID_BLKID_H */ +#endif /* HAVE_LIBUDEV_H */ + +#endif /* HAVE_WINDOWS_H */ diff --git a/src/uuidlookup.h b/src/uuidlookup.h new file mode 100644 index 0000000..c6da73e --- /dev/null +++ b/src/uuidlookup.h @@ -0,0 +1,37 @@ +/* uuidlookup.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __UUIDLOOKUP_H_ +#define __UUIDLOOKUP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int GetMountpointFromUUID(char *mountp, size_t mountp_sz, const char *uuid_str); + +#ifdef __cplusplus +} +#endif + +#endif /* __UUIDLOOKUP_H_ */ diff --git a/src/vchanger.cpp b/src/vchanger.cpp new file mode 100644 index 0000000..2d2859a --- /dev/null +++ b/src/vchanger.cpp @@ -0,0 +1,661 @@ +/* vchanger.cpp + * + * This file is part of the vchanger package + * + * vchanger copyright (C) 2008-2015 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" +#ifdef HAVE_STDIO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_GETOPT_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_CTYPE_H +#include +#endif +#ifdef HAVE_LOCALE_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#include "util.h" +#include "compat_defs.h" +#include "loghandler.h" +#include "diskchanger.h" + +DiskChanger changer; + +/*------------------------------------------------- + * Commands + * ------------------------------------------------*/ +#define NUM_AUTOCHANGER_COMMANDS 9 +static char autochanger_command[NUM_AUTOCHANGER_COMMANDS][32] = { "list", "slots", "load", + "unload", "loaded", "listall", "listmags", "createvols", "refresh" }; +#define CMD_LIST 0 +#define CMD_SLOTS 1 +#define CMD_LOAD 2 +#define CMD_UNLOAD 3 +#define CMD_LOADED 4 +#define CMD_LISTALL 5 +#define CMD_LISTMAGS 6 +#define CMD_CREATEVOLS 7 +#define CMD_REFRESH 8 + +/*------------------------------------------------- + * Command line parameters + * ------------------------------------------------*/ +typedef struct _cmdparams_s +{ + bool print_version; + bool print_help; + int command; + int slot; + int drive; + int mag_bay; + int count; + tString label_prefix; + tString pool; + tString runas_user; + tString runas_group; + tString config_file; + tString archive_device; +} CMDPARAMS; +CMDPARAMS cmdl; + +/*------------------------------------------------- + * Function to print version info to stdout + *------------------------------------------------*/ +static void print_version(void) +{ + fprintf(stdout, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); + fprintf(stdout, "\n%s.\n", COPYRIGHT_NOTICE); +} + +/*------------------------------------------------- + * Function to print command help to stdout + *------------------------------------------------*/ +static void print_help(void) +{ + fprintf(stdout, "vchanger version %s\n\n", PACKAGE_VERSION); + fprintf(stdout, "USAGE:\n\n" + " vchanger [options] config_file command slot device drive\n" + " Perform Bacula Autochanger API command for virtual\n" + " changer defined by vchanger configuration file\n" + " 'config_file' using 'slot', 'device', and 'drive'\n" + " vchanger [options] config_file LISTMAGS\n" + " vchanger extension to list info on all defined magazines.\n" + " vchanger [options] config_file CREATEVOLS mag_ndx count [start] [CREATEVOLS options]\n" + " vchanger extension to create 'count' empty volume files on the magazine at\n" + " index 'mag_ndx'. If specified, 'start' is the lowest integer to use when\n" + " appending integers to the label prefix when generating volume names.\n" + " vchanger [options] config_file REFRESH\n" + " vchanger --version\n" + " print version info\n" + " vchanger --help\n" + " print help\n" + "\nGeneral options:\n" + " -u, --user=uid user to run as (when invoked by root)\n" + " -g, --group=gid group to run as (when invoked by root)\n" + "\nCREATEVOLS command options:\n" + " -l, --label=string string to use as a prefix for determining the\n" + " barcode label of the volume files created. Labels\n" + " will be of the form 'string'_N, where N is an\n" + " integer. By default the prefix will be generated\n" + " using the changer name and the position of the\n" + " magazine's declaration in the configuration file.\n" + " --pool=string Overrides the default pool, defined in the vchanger\n" + " config file, that new volumes should be placed into\n" + " when labeling newly created volumes.\n" + "\nReport bugs to %s.\n", PACKAGE_BUGREPORT); +} + +/*------------------------------------------------- + * Function to parse command line parameters + *------------------------------------------------*/ +#define LONGONLYOPT_VERSION 0 +#define LONGONLYOPT_HELP 1 +#define LONGONLYOPT_POOL 2 + +static int parse_cmdline(int argc, char *argv[]) +{ + int c, ndx = 0; + tString tmp; + struct option options[] = { { "version", 0, 0, LONGONLYOPT_VERSION }, + { "help", 0, 0, LONGONLYOPT_HELP }, + { "user", 1, 0, 'u' }, + { "group", 1, 0, 'g' }, + { "label", 1, 0, 'l' }, + { "pool", 1, 0, LONGONLYOPT_POOL }, + { 0, 0, 0, 0 } }; + + cmdl.print_version = false; + cmdl.print_help = false; + cmdl.command = 0; + cmdl.slot = 0; + cmdl.drive = 0; + cmdl.mag_bay = 0; + cmdl.count = 0; + cmdl.label_prefix.clear(); + cmdl.pool.clear(); + cmdl.runas_user.clear(); + cmdl.runas_group.clear(); + cmdl.config_file.clear(); + cmdl.archive_device.clear(); + /* process the command line */ + for (;;) { + c = getopt_long(argc ,argv, "u:g:l:", options, NULL); + if (c == -1) break; + switch (c) { + case LONGONLYOPT_VERSION: + cmdl.print_version = true; + cmdl.print_help = false; + return 0; + case LONGONLYOPT_HELP: + cmdl.print_version = false; + cmdl.print_help = true; + return 0; + case 'u': + cmdl.runas_user = optarg; + break; + case 'g': + cmdl.runas_group = optarg; + break; + case 'l': + cmdl.label_prefix = optarg; + break; + case LONGONLYOPT_POOL: + cmdl.pool = optarg; + break; + default: + fprintf(stderr, "unknown option %s\n", optarg); + return -1; + } + } + + /* process positional params */ + ndx = optind; + /* First parameter is the vchanger config file path */ + if (ndx >= argc) { + fprintf(stderr, "missing parameter 1 (config_file)\n"); + return -1; + } + cmdl.config_file = argv[ndx]; + /* Second parameter is the command */ + ++ndx; + if (ndx >= argc) { + fprintf(stderr, "missing parameter 2 (command)\n"); + return -1; + } + tmp = argv[ndx]; + tToLower(tStrip(tmp)); + for (cmdl.command = 0; cmdl.command < NUM_AUTOCHANGER_COMMANDS; cmdl.command++) { + if (tmp == autochanger_command[cmdl.command]) break; + } + if (cmdl.command >= NUM_AUTOCHANGER_COMMANDS) { + fprintf(stderr, "'%s' is not a recognized command", argv[ndx]); + return -1; + } + /* Make sure only CREATEVOLS command has -l flag */ + if (!cmdl.label_prefix.empty() && cmdl.command != CMD_CREATEVOLS) { + fprintf(stderr, "flag -l not valid for this command\n"); + return -1; + } + /* Make sure only CREATEVOLS command has --pool flag */ + if (!cmdl.pool.empty() && cmdl.command != CMD_CREATEVOLS) { + fprintf(stderr, "flag --pool not valid for this command\n"); + return -1; + } + /* Check param 3 exists */ + ++ndx; + if (ndx >= argc) { + /* Only 2 parameters given */ + switch (cmdl.command) { + case CMD_LIST: + case CMD_LISTALL: + case CMD_SLOTS: + case CMD_LISTMAGS: + case CMD_REFRESH: + return 0; /* OK, because these commands only need 2 parameters */ + case CMD_CREATEVOLS: + fprintf(stderr, "missing parameter 3 (magazine index)\n"); + break; + default: + fprintf(stderr, "missing parameter 3 (slot number)\n"); + break; + } + return -1; + } + /* Process parameter 3 */ + switch (cmdl.command) { + case CMD_LIST: + case CMD_LISTALL: + case CMD_SLOTS: + case CMD_LISTMAGS: + case CMD_REFRESH: + return 0; /* These commands only need 2 params, so ignore extraneous */ + case CMD_CREATEVOLS: + /* Param 3 for CREATEVOLS command is magazine index */ + cmdl.mag_bay = (int)strtol(argv[ndx], NULL, 10); + if (cmdl.mag_bay < 0) { + fprintf(stderr, "invalid magazine index in parameter 3\n"); + return -1; + } + break; + case CMD_LOADED: + /* slot is ignored for LOADED command, so just set to 1 */ + cmdl.slot = 1; + break; + default: + /* Param 3 for all other commands is the slot number */ + cmdl.slot = (int)strtol(argv[ndx], NULL, 10); + if (cmdl.slot < 1) { + fprintf(stderr, "invalid slot number in parameter 3\n"); + return -1; + } + break; + } + /* Check param 4 exists */ + ++ndx; + if (ndx >= argc) { + /* Only 3 parameters given */ + switch (cmdl.command) { + case CMD_CREATEVOLS: + fprintf(stderr, "missing parameter 4 (count)\n"); + break; + default: + fprintf(stderr, "missing parameter 4 (archive device)\n"); + break; + } + return -1; + } + /* Process param 4 */ + switch (cmdl.command) { + case CMD_CREATEVOLS: + /* Param 4 for CREATEVOLS command is volume count */ + cmdl.count = (int)strtol(argv[ndx], NULL, 10); + if (cmdl.count <= 0 ) { + fprintf(stderr, "invalid count in parameter 4\n"); + return -1; + } + break; + default: + /* Param 4 for all other commands is the archive device path */ + cmdl.archive_device = argv[ndx]; + break; + } + /* Check param 5 exists */ + ++ndx; + if (ndx >= argc) { + /* Only 4 parameters given */ + switch (cmdl.command) { + case CMD_CREATEVOLS: + cmdl.slot = -1; + return 0; /* OK, because parameter 5 optional */ + default: + fprintf(stderr, "missing parameter 5 (drive index)\n"); + break; + } + return -1; + } + switch (cmdl.command) { + case CMD_CREATEVOLS: + cmdl.slot = (int)strtol(argv[ndx], NULL, 10); + if (cmdl.slot < 0) cmdl.slot = -1; + break; + default: + /* Param 5 for all other commands is drive index number */ + if (!isdigit(argv[ndx][0])) { + fprintf(stderr, "invalid drive index in parameter 5\n"); + return -1; + } + cmdl.drive = (int)strtol(argv[ndx], NULL, 10); + if (cmdl.drive < 0) { + fprintf(stderr, "invalid drive index in parameter 5\n"); + return -1; + } + break; + } + + /* note that any extraneous parameters are simply ignored */ + return 0; +} + + +/*------------------------------------------------- + * LIST Command + * Prints a line on stdout for each autochanger slot that contains a + * volume file, even if that volume is currently loaded in a drive. + * Output is of the form: + * s:barcode + * where 's' is the one-based virtual slot number and 'barcode' is the barcode + * label of the volume in the slot. The volume in the slot is a file on one + * of the changer's magazines. A magazine is a directory, which is usually the + * mountpoint of a filesystem partition. The changer has one or more + * magazines, each of which may or may not be attached. Each volume file on + * each magazine is mapped to a virtual slot. The barcode is the volume filename. + *------------------------------------------------*/ +static int do_list_cmd() +{ + int slot, num_slots = changer.NumSlots(); + + /* Print all slot numbers, adding volume labels for non-empty slots */ + for (slot = 1; slot <= num_slots; slot++) { + if (changer.SlotEmpty(slot)) { + fprintf(stdout, "%d:\n", slot); + } else { + fprintf(stdout, "%d:%s\n", slot, changer.GetVolumeLabel(slot)); + } + } + log.Info(" SUCCESS sent list to stdout"); + return 0; +} + + +/*------------------------------------------------- + * SLOTS Command + * Prints the number of virtual slots the changer has + *------------------------------------------------*/ +static int do_slots_cmd() +{ + fprintf(stdout, "%d\n", changer.NumSlots()); + log.Info(" SUCCESS reporting %d slots", changer.NumSlots()); + return 0; +} + + +/*------------------------------------------------- + * LOAD Command + * Loads the volume file mapped to a virtual slot into a virtual drive + *------------------------------------------------*/ +static int do_load_cmd() +{ + if (changer.LoadDrive(cmdl.drive, cmdl.slot)) { + fprintf(stderr, "%s\n", changer.GetErrorMsg()); + log.Error(" ERROR loading slot %d into drive %d", cmdl.slot, cmdl.drive); + return 1; + } + log.Info(" SUCCESS loading slot %d into drive %d", cmdl.slot, cmdl.drive); + return 0; +} + + +/*------------------------------------------------- + * UNLOAD Command + * Unloads the volume in a virtual drive + *------------------------------------------------*/ +static int do_unload_cmd() +{ + if (changer.UnloadDrive(cmdl.drive)) { + fprintf(stderr, "%s\n", changer.GetErrorMsg()); + log.Error(" ERROR unloading slot %d from drive %d", cmdl.slot, cmdl.drive); + return 1; + } + log.Info(" SUCCESS unloading slot %d from drive %d", cmdl.slot, cmdl.drive); + return 0; +} + + +/*------------------------------------------------- + * LOADED Command + * Prints the virtual slot number of the volume file currently loaded + * into a virtual drive, or zero if the drive is unloaded. + *------------------------------------------------*/ +static int do_loaded_cmd() +{ + int slot = changer.GetDriveSlot(cmdl.drive); + if (slot < 0) slot = 0; + fprintf(stdout, "%d\n", slot); + log.Info(" SUCCESS reporting drive %d loaded from slot %d", cmdl.drive, slot); + return 0; +} + +/*------------------------------------------------- + * LISTALL Command + * Prints state of drives (loaded or empty), followed by state + * of virtual slots (full or empty). + *------------------------------------------------*/ +static int do_list_all() +{ + int n, s, num_slots = changer.NumSlots(); + + /* Print drive state info */ + for (n = 0; n < changer.NumDrives(); n++) { + if (changer.DriveEmpty(n)) { + fprintf(stdout, "D:%d:E\n", n); + } else { + s = changer.GetDriveSlot(n); + fprintf(stdout, "D:%d:F:%d:%s\n", n, s, + changer.GetVolumeLabel(s)); + } + } + /* Print slot state info */ + for (n = 1; n <= num_slots; n++) { + if (changer.SlotEmpty(n)) { + fprintf(stdout, "S:%d:E\n", n); + } else { + if (changer.GetSlotDrive(n) < 0) + fprintf(stdout, "S:%d:F:%s\n", n, changer.GetVolumeLabel(n)); + else + fprintf(stdout, "S:%d:E\n", n); + } + } + log.Info(" SUCCESS sent listall to stdout"); + return 0; +} + + +/*------------------------------------------------- + * LISTMAGS (List Magazines) Command + * Prints a listing of all magazine bays and info on the magazine + * (if any) each bay contains. + *------------------------------------------------*/ +static int do_list_magazines() +{ + int n; + + if (changer.NumMagazines() == 0) { + fprintf(stdout, "No magazines are defined\n"); + log.Info(" SUCCESS no magazines are defined"); + return 0; + } + for (n = 0; n < changer.NumMagazines(); n++) { + if (changer.MagazineEmpty(n)) { + fprintf(stdout, "%d:::\n", n); + } else { + fprintf(stdout, "%d:%d:%d:%s\n", n, changer.GetMagazineSlots(n), + changer.GetMagazineStartSlot(n), changer.GetMagazineMountpoint(n)); + } + } + log.Info(" SUCCESS listing magazine info to stdout"); + return 0; +} + +/*------------------------------------------------- + * CREATEVOLS (Create Volumes) Command + * Creates volume files on the specified magazine + *------------------------------------------------*/ +static int do_create_vols() +{ + /* Create new volume files on magazine */ + if (changer.CreateVolumes(cmdl.mag_bay, cmdl.count, cmdl.slot, cmdl.label_prefix.c_str())) { + fprintf(stderr, "%s\n", changer.GetErrorMsg()); + log.Error(" ERROR"); + return -1; + } + fprintf(stdout, "Created %d volume files on magazine %d\n", + cmdl.count, cmdl.mag_bay); + log.Info(" SUCCESS"); + return 0; +} + + + +/* ------------- Main -------------------------*/ + +int main(int argc, char *argv[]) +{ + int rc; + FILE *fs = NULL; + int32_t error_code; + +#ifdef HAVE_LOCALE_H + setlocale(LC_ALL, ""); +#endif + + /* Log initially to stderr */ + log.OpenLog(stderr, LOG_ERR); + /* parse the command line */ + if ((error_code = parse_cmdline(argc, argv)) != 0) { + print_help(); + return 1; + } + /* Check for --version flag */ + if (cmdl.print_version) { + print_version(); + return 0; + } + /* Check for --help flag */ + if (cmdl.print_help) { + print_help(); + return 0; + } + /* Read vchanger config file */ + if (!conf.Read(cmdl.config_file)) { + return 1; + } + /* User:group from cmdline overrides config file values */ + if (cmdl.runas_user.size()) conf.user = cmdl.runas_user; + if (cmdl.runas_group.size()) conf.group = cmdl.runas_group; + /* Pool from cmdline overrides config file */ + if (!cmdl.pool.empty()) conf.def_pool = cmdl.pool; + /* If root, try to run as configured user:group */ + rc = drop_privs(conf.user.c_str(), conf.group.c_str()); + if (rc) { + fprintf(stderr, "Error %d attempting to run as user '%s'", rc, conf.user.c_str()); + return 1; + } + /* Start logging to log file specified in configuration file */ + if (!conf.logfile.empty()) { + fs = fopen(conf.logfile.c_str(), "a"); + if (fs == NULL) { + fprintf(stderr, "Error opening opening log file\n"); + return 1; + } + log.OpenLog(fs, conf.log_level); + } + /* Validate and commit configuration parameters */ + if (!conf.Validate()) { + return 1; + } +#ifndef HAVE_WINDOWS_H + /* Ignore SIGPIPE signals */ + signal(SIGPIPE, SIG_IGN); +#endif + /* Initialize changer. A lock file is created to serialize access + * to the changer. As a result, changer initialization may block + * for up to 30 seconds, and may fail if a timeout is reached */ + if (changer.Initialize()) { + fprintf(stderr, "%s\n", changer.GetErrorMsg()); + return 1; + } + + /* Perform command */ + switch (cmdl.command) { + case CMD_LIST: + log.Debug("==== preforming LIST command pid=%d", getpid()); + error_code = do_list_cmd(); + break; + case CMD_SLOTS: + log.Debug("==== preforming SLOTS command pid=%d", getpid()); + error_code = do_slots_cmd(); + break; + case CMD_LOAD: + log.Debug("==== preforming LOAD command pid=%d", getpid()); + error_code = do_load_cmd(); + break; + case CMD_UNLOAD: + log.Debug("==== preforming UNLOAD command pid=%d", getpid()); + error_code = do_unload_cmd(); + break; + case CMD_LOADED: + log.Debug("==== preforming LOADED command pid=%d", getpid()); + error_code = do_loaded_cmd(); + break; + case CMD_LISTALL: + log.Debug("==== preforming LISTALL command pid=%d", getpid()); + error_code = do_list_all(); + break; + case CMD_LISTMAGS: + log.Debug("==== preforming LISTMAGS command pid=%d", getpid()); + error_code = do_list_magazines(); + break; + case CMD_CREATEVOLS: + log.Debug("==== preforming CREATEVOLS command pid=%d", getpid()); + error_code = do_create_vols(); + break; + case CMD_REFRESH: + log.Debug("==== preforming REFRESH command pid=%d", getpid()); + error_code = 0; + log.Info(" SUCCESS pid=%d", getpid()); + break; + } + changer.Unlock(); + + /* If there was an error, then exit */ + if (error_code) return error_code; + + /* If not updating Bacula, then exit */ + if (conf.bconsole.empty()) { + /* Bacula interaction via bconsole is disabled, so log warnings */ + if (changer.NeedsUpdate()) + log.Error("WARNING! 'update slots' needed in bconsole pid=%d", getpid()); + if (changer.NeedsLabel()) + log.Error("WARNING! 'label barcodes' needed in bconsole pid=%d", getpid()); + return 0; + } + + /* Update Bacula via bconsole */ +#ifndef HAVE_WINDOWS_H + changer.UpdateBacula(); +#else + /* Auto-update of bacula not working for Windows */ + if (changer.NeedsUpdate()) + log.Error("WARNING! 'update slots' needed in bconsole"); + if (changer.NeedsLabel()) + log.Error("WARNING! 'label barcodes' needed in bconsole"); +#endif + + return 0; +} diff --git a/src/vconf.cpp b/src/vconf.cpp new file mode 100644 index 0000000..167cf63 --- /dev/null +++ b/src/vconf.cpp @@ -0,0 +1,309 @@ +/* vconf.cpp + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Provides class for reading configuration file and providing access + * to config variables. + */ + +#include "config.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_SYSLOG_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_WINDOWS_H +#include "targetver.h" +#include +#include +#include +#define DIR_DELIM "\\" +#define DIR_DELIM_C '\\' +#define MAG_VOLUME_MASK 0 +#else +#define DIR_DELIM "/" +#define DIR_DELIM_C '/' +#define MAG_VOLUME_MASK S_IWGRP|S_IRWXO +#endif + +#include "loghandler.h" +#include "util.h" +#define __VCONF_SOURCE 1 +#include "vconf.h" + +/* Global configuration object */ +VchangerConfig conf; + +/*------------------------------------------- + * Config file keywords and defaults + *-------------------------------------------*/ + +#define VK_STORAGE_NAME "storage resource" +#define VK_MAGAZINE "magazine" +#define VK_WORK_DIR "work dir" +#define VK_LOGFILE "logfile" +#define VK_LOG_LEVEL "log level" +#define VK_USER "user" +#define VK_GROUP "group" +#define VK_BCONSOLE "bconsole" +#define VK_BCONSOLE_CONFIG "bconsole config" +#define VK_DEF_POOL "default pool" + + +/*================================================ + * Class VchangerConfig + *================================================*/ + +/*-------------------------------------------------- + * Default constructor + *------------------------------------------------*/ +VchangerConfig::VchangerConfig() : log_level(DEFAULT_LOG_LEVEL) +{ +#ifdef HAVE_WINDOWS_H + char tmp[4096]; + wchar_t wtmp[2048]; +#endif + storage_name = DEFAULT_STORAGE_NAME; + /* Set default Bacula work directory and vchanger config file path */ +#ifdef HAVE_WINDOWS_H + /* Bacula installs its work directory in the FOLDERID_ProgramData folder, which + * is in a different location depending on Windows version. */ + wtmp[0] = 0; + memset(tmp, 0, sizeof(tmp)); + if (SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, wtmp) == S_OK) { + wcstombs(tmp, wtmp, sizeof(tmp) - 1); + snprintf(DEFAULT_STATEDIR, sizeof(DEFAULT_STATEDIR), "%s%svchanger", tmp, DIR_DELIM); + snprintf(DEFAULT_LOGDIR, sizeof(DEFAULT_LOGDIR), "%s%svchanger", tmp, DIR_DELIM); + } +#else + snprintf(DEFAULT_STATEDIR, sizeof(DEFAULT_STATEDIR), "%s/spool/vchanger", LOCALSTATEDIR); + snprintf(DEFAULT_LOGDIR, sizeof(DEFAULT_LOGDIR), "%s/log/vchanger", LOCALSTATEDIR); +#endif + tFormat(work_dir, "%s%s%s", DEFAULT_STATEDIR, DIR_DELIM, storage_name.c_str()); + /* Set default logfile path and log level */ + tFormat(logfile, "%s%s%s.log", DEFAULT_LOGDIR, DIR_DELIM, storage_name.c_str()); + /* Set default runas user and group */ + user = DEFAULT_USER; + group = DEFAULT_GROUP; + /* Set default bconsole binary path */ + bconsole = DEFAULT_BCONSOLE; + /* Set default pool for created volumes */ + def_pool = DEFAULT_POOL; + /* Define config file keywords */ + keyword.AddKeyword(VK_MAGAZINE, INIKEYWORDTYPE_MULTISZ); + keyword.AddKeyword(VK_WORK_DIR, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_LOGFILE, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_LOG_LEVEL, INIKEYWORDTYPE_LONG); + keyword.AddKeyword(VK_USER, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_GROUP, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_BCONSOLE, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_BCONSOLE_CONFIG, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_STORAGE_NAME, INIKEYWORDTYPE_SZ); + keyword.AddKeyword(VK_DEF_POOL, INIKEYWORDTYPE_SZ); +} + +/*------------------------------------------------- + * Method to read config file and set config values from keyword + * value pairs. On success, returns true. Otherwise returns false. + *------------------------------------------------*/ +bool VchangerConfig::Read(const char *cfile) +{ + int rc, n; + IniFile tmp_ini = keyword; + + tmp_ini.ClearKeywordValues(); + if (!cfile || !cfile[0]) { + log.Error("config file not specified"); + return false; + } + /* Does config file exist */ + if (access(cfile, R_OK)) { + log.Error("could not access config file %s", cfile); + return false; + } + /* Read config file values */ + rc = tmp_ini.Read(cfile); + if (rc) { + if (rc > 0) log.Error("Parse error in %s at line %d", cfile, rc); + else log.Error("could not open config file %s", cfile); + return false; + } + /* Update keyword values */ + keyword.Update(tmp_ini); + + /* Get bacula-dir.conf storage resource name associated with this changer name */ + if (keyword[VK_STORAGE_NAME].IsSet()) { + storage_name = (const char*)keyword[VK_STORAGE_NAME]; + tStrip(storage_name); + if (storage_name.empty()) { + log.Error("config file keyword '%s' must specify a non-empty string", VK_STORAGE_NAME); + return false; + } + /* Update defaults for this changer name */ + tFormat(work_dir, "%s%s%s", DEFAULT_STATEDIR, DIR_DELIM, storage_name.c_str()); + tFormat(logfile, "%s%s%s.log", DEFAULT_LOGDIR, DIR_DELIM, storage_name.c_str()); + } + + /* Get work directory for this changer */ + if (keyword[VK_WORK_DIR].IsSet()) { + work_dir = (const char*)keyword[VK_WORK_DIR]; + tStrip(work_dir); + if (work_dir.empty()) { + log.Error("config file keyword '%s' must specify a non-empty string", VK_WORK_DIR); + return false; + } + } + + /* Get logfile path */ + if (keyword[VK_LOGFILE].IsSet()) { + logfile = (const char*)keyword[VK_LOGFILE]; + tStrip(logfile); + if (logfile.empty()) { + log.Error("config file keyword '%s' must specify a non-empty string", VK_LOGFILE); + return false; + } + } + + /* Get log level */ + if (keyword[VK_LOG_LEVEL].IsSet()) { + log_level = (int)keyword[VK_LOG_LEVEL]; + if (log_level < 0 || log_level > 7) { + log.Error("config file keyword '%s' must specify a value between 0 and 7 inclusive", VK_LOG_LEVEL); + return false; + } + } + + /* Get user to run as */ + if (keyword[VK_USER].IsSet()) { + user = (const char*)keyword[VK_USER]; + tStrip(user); + if (user.empty()) { + log.Error("keyword '%s' value cannot be empty", VK_USER); + return false; + } + } + + /* Get group to run as */ + if (keyword[VK_GROUP].IsSet()) { + group = (const char*)keyword[VK_GROUP]; + tStrip(group); + if (group.empty()) { + log.Error("keyword '%s' value cannot be empty", VK_GROUP); + return false; + } + } + + /* Get path of bconsole binary */ + if (keyword[VK_BCONSOLE].IsSet()) { + bconsole = (const char*)keyword[VK_BCONSOLE]; + tStrip(bconsole); + } + + /* Get path of bconsole config file */ + if (keyword[VK_BCONSOLE_CONFIG].IsSet()) { + bconsole_config = (const char*)keyword[VK_BCONSOLE_CONFIG]; + tStrip(bconsole_config); + } + + /* Get default pool */ + if (keyword[VK_DEF_POOL].IsSet()) { + def_pool = (const char*)keyword[VK_DEF_POOL]; + tStrip(def_pool); + if (def_pool.empty()) { + log.Error("keyword '%s' value cannot be empty", VK_DEF_POOL); + return false; + } + } + + /* Get list of assigned magazines */ + if (keyword[VK_MAGAZINE].IsSet()) { + magazine = keyword[VK_MAGAZINE]; + } + if (magazine.empty()) { + log.Error("config file keyword '%s' must appear at least once", VK_MAGAZINE); + return false; + } + for (n = 0; n < (int)magazine.size(); n++) { + tStrip(magazine[n]); + if (magazine[n].empty()) { + log.Error("config file keyword '%s' cannot be set to the empty string", VK_MAGAZINE); + return false; + } + } + return true; +} + +/*------------------------------------------------- + * Method to validate config file values and commit default + * values for any keywords not specified + *------------------------------------------------*/ +bool VchangerConfig::Validate() +{ + mode_t old_mask; + + /* Validate work directory is usable */ + if (access(work_dir.c_str(), W_OK)) { + if (errno == ENOENT) { + /* If not found then try to create work dir */ + old_mask = umask(027); +#ifndef HAVE_WINDOWS_H + if (mkdir(work_dir.c_str(), 0770)) { +#else + if (_mkdir(work_dir.c_str())) { +#endif + log.Error("could not create work directory '%s'", work_dir.c_str()); + umask(old_mask); + return false; + } + umask(old_mask); + } else { + log.Error("could not access work directory '%s'", work_dir.c_str()); + return false; + } + } + + /* Validate bconsole config file is readable */ + if (bconsole.empty()) bconsole_config.clear(); + if (!bconsole_config.empty()) { + if (access(bconsole_config.c_str(), R_OK)) { + /* If bconsole config doesn't exist or is not readable, disable use of bconsole */ + log.Warning("cannot read bconsole config file. Disabling Bacula interaction."); + bconsole.clear(); + bconsole_config.clear(); + } + } + + return true; +} diff --git a/src/vconf.h b/src/vconf.h new file mode 100644 index 0000000..f36df28 --- /dev/null +++ b/src/vconf.h @@ -0,0 +1,70 @@ +/* vconf.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2014 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef _VCONF_H_ +#define _VCONF_H_ 1 + +#include "inifile.h" + +#define DEFAULT_LOG_LEVEL 3 +#define DEFAULT_USER "bacula" +#define DEFAULT_GROUP "tape" +#define DEFAULT_BCONSOLE "/usr/sbin/bconsole" +#define DEFAULT_STORAGE_NAME "vchanger" +#define DEFAULT_POOL "Scratch" + +/* Configuration values */ + +class VchangerConfig +{ +public: + IniFile keyword; + tString work_dir; + tString config_file; + tString logfile; + int log_level; + tString user; + tString group; + tString bconsole; + tString bconsole_config; + tString storage_name; + tString def_pool; + tStringArray magazine; +public: + VchangerConfig(); + virtual ~VchangerConfig() {} + bool Read(const char *cfile); + inline bool Read(const tString &cfile) { return Read(cfile.c_str()); } + bool Validate(); +}; + +#ifndef __VCONF_SOURCE +extern VchangerConfig conf; +extern char DEFAULT_LOGDIR[4096]; +extern char DEFAULT_STATEDIR[4096]; +#else +char DEFAULT_LOGDIR[4096]; +char DEFAULT_STATEDIR[4096]; +#endif + +#endif /* _VCONF_H_ */ diff --git a/src/win32_util.c b/src/win32_util.c new file mode 100644 index 0000000..02b6eeb --- /dev/null +++ b/src/win32_util.c @@ -0,0 +1,259 @@ +/* win32_util.c + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2012 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#ifdef HAVE_WINDOWS_H + +#include "targetver.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif + +#include "win32_util.h" + +#ifndef ENODATA +#define ENODATA EIO +#endif +#ifndef ENOMEDIUM +#define ENOMEDIUM ENOSPC +#endif + +/*------------------------------------------------- + * Convert 100 ns intervals since 1601-01-01 00:00:00 UTC in 'ftime' to + * seconds since 1970-01-01 00:00:00 UTC and return as type time_t. + *-------------------------------------------------*/ +time_t ftime2utime(const FILETIME *ftime) +{ + uint64_t ut = ftime->dwHighDateTime; + ut <<= 32; + ut |= ftime->dwLowDateTime; /* 100 ns intervals since FILETIME epoch */ + ut -= EPOCH_FILETIME; /* convert to 100 ns intervals since Unix epoch */ + ut /= 10000000; /* convert to seconds since Unix epoch */ + return (time_t)ut; +} + + +/*------------------------------------------------- + * Utility function to convert an ANSI string 'str' to a UTF-16 string. + * 'u16str' is pointer to a pointer to a caller supplied buffer where the + * UTF-16 string will be created. 'u16size' is a pointer to a size_t variable + * that contains the size of the supplied buffer. On entry, if the pointer that + * 'u16str' points to is NULL, then a buffer for the result UTF-16 string will + * be allocated using malloc. A pointer to the allocated buffer will be + * returned in *u16str and the size of the allocated buffer (in bytes) will be + * returned in *u16size. It is the caller's responsibility to free the + * allocated buffer. If the caller supplies a buffer then no memory will be + * allocated, and if the buffer is too small then NULL will be returned. + * On success, a pointer to the UTF-16 string is returned. + * On error, NULL is returned. + *-------------------------------------------------*/ +wchar_t* AnsiToUTF16(const char *str, wchar_t **u16str, size_t *u16size) +{ + size_t needed; + UINT acp = GetACP(); /* Use current active code page for conversion */ + + if (!str) { + return NULL; /* NULL input string is an error */ + } + /* Determine size of buffer needed for the UTF-16 string */ + needed = MultiByteToWideChar(acp, 0, str, -1, NULL, 0); + if (*u16str) { + /* If caller supplied a buffer, check that it's large enough */ + if (*u16size < needed) { + return NULL; /* caller's buffer is too small */ + } + } else { + /* If caller did not supply buffer, then allocate one */ + *u16size = needed * sizeof(wchar_t); + *u16str = (wchar_t*)malloc(*u16size); + } + /* Do the ANSI to UTF-16 conversion */ + MultiByteToWideChar(acp, 0, str, -1, *u16str, *u16size); + return *u16str; +} + + +/*------------------------------------------------- + * Utility function to convert UTF-16 string 'u16str' to an ANSI string. + * 'str' is a pointer to a pointer to a caller supplied buffer where the UTF-8 + * string will be created. 'str_size' is a pointer to a size_t variable that + * contains the size of the supplied buffer. On entry, if the pointer that + * 'str' points to is NULL, then a buffer for the result ANSI string will + * be allocated using malloc. A pointer to the allocated buffer will be + * returned in *str and the size of the allocated buffer (in bytes) will + * be returned in *str_size. It is the caller's responsibility to free the + * allocated buffer.If the caller supplies a buffer then no memory will be + * allocated, and if the buffer is too small then NULL will be returned. + * On success, a pointer to the ANSI string is returned. + * On error, NULL is returned. + *-------------------------------------------------*/ +char *UTF16ToAnsi(const wchar_t *u16str, char **str, size_t *str_size) +{ + size_t needed; + UINT acp = GetACP(); /* Use current code page for conversion */ + + if (!u16str) { + return NULL; /* NULL input string is an error */ + } + /* Determine size of buffer needed for UTF-8 string */ + needed = WideCharToMultiByte(acp, 0, u16str, -1, NULL, 0, NULL, NULL); + if (*str) { + /* If caller supplied a buffer, check that it's large enough */ + if (*str_size < needed) { + return NULL; // caller's buffer is too small */ + } + } else { + /* If caller did not supply buffer, then allocate one */ + *str_size = needed; + *str = (char*)malloc(*str_size); + } + /* Do the UTF-16 to ANSI conversion */ + WideCharToMultiByte(acp, 0, u16str, -1, *str, *str_size, NULL, NULL); + return *str; +} + + +/*------------------------------------------------- + * Translate win32 error codes to errno + *-------------------------------------------------*/ +int w32errno(DWORD werr) +{ + switch (werr) { + case ERROR_SUCCESS: + return 0; + case ERROR_ACCESS_DENIED: + case ERROR_SHARING_VIOLATION: + case ERROR_LOCK_VIOLATION: + return EACCES; + case ERROR_NO_PROC_SLOTS: + case ERROR_MORE_DATA: + case ERROR_MAX_THRDS_REACHED: + case ERROR_ACTIVE_CONNECTIONS: + case ERROR_DEVICE_IN_USE: + return EAGAIN; + case ERROR_INVALID_HANDLE: + return EBADF; + case ERROR_BUSY: + case ERROR_PIPE_BUSY: + case ERROR_PIPE_CONNECTED: + case ERROR_SIGNAL_PENDING: + case ERROR_CHILD_NOT_COMPLETE: + return EBUSY; + case ERROR_WAIT_NO_CHILDREN: + return ECHILD; + case ERROR_POSSIBLE_DEADLOCK: + return EDEADLOCK; + case ERROR_FILE_EXISTS: + case ERROR_ALREADY_EXISTS: + return EEXIST; + case ERROR_PROCESS_ABORTED: + case ERROR_NOACCESS: + return EFAULT; + case ERROR_INVALID_AT_INTERRUPT_TIME: + return EINTR; + case ERROR_INVALID_DATA: + case ERROR_INVALID_PARAMETER: + case ERROR_FILENAME_EXCED_RANGE: + case ERROR_META_EXPANSION_TOO_LONG: + case ERROR_INVALID_SIGNAL_NUMBER: + case ERROR_THREAD_1_INACTIVE: + case ERROR_BAD_PIPE: + case ERROR_NO_TOKEN: + case ERROR_NEGATIVE_SEEK: + case ERROR_BAD_USERNAME: + return EINVAL; + case ERROR_OPEN_FAILED: + case ERROR_SIGNAL_REFUSED: + case ERROR_NO_SIGNAL_SENT: + case ERROR_IO_DEVICE: + case ERROR_CRC: + return EIO; + case ERROR_TOO_MANY_OPEN_FILES: + return EMFILE; + case ERROR_NO_MORE_SEARCH_HANDLES: + case ERROR_NO_MORE_FILES: + return ENFILE; + case ERROR_HANDLE_EOF: + return ENODATA; + case ERROR_BAD_DEVICE: + case ERROR_BAD_UNIT: + case ERROR_INVALID_DRIVE: + return ENODEV; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + case ERROR_INVALID_NAME: + case ERROR_BAD_PATHNAME: + case ERROR_BAD_NETPATH: + case ERROR_BAD_NET_NAME: + return ENOENT; + case ERROR_SHARING_BUFFER_EXCEEDED: + return ENOLCK; + case ERROR_NOT_CONNECTED: + case ERROR_NOT_READY: + return ENOMEDIUM; + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUTOFMEMORY: + return ENOMEM; + case ERROR_DISK_FULL: + case ERROR_END_OF_MEDIA: + case ERROR_EOM_OVERFLOW: + case ERROR_NO_DATA_DETECTED: + case ERROR_HANDLE_DISK_FULL: + return ENOSPC; + case ERROR_CALL_NOT_IMPLEMENTED: + case ERROR_NOT_SUPPORTED: + return ENOSYS; + case ERROR_DIRECTORY: + return ENOTDIR; + case ERROR_DIR_NOT_EMPTY: + return ENOTEMPTY; + case ERROR_FILE_INVALID: + return ENXIO; + case ERROR_NOT_OWNER: + case ERROR_CANNOT_MAKE: + return EPERM; + case ERROR_BROKEN_PIPE: + case ERROR_NO_DATA: + return EPIPE; + case ERROR_WRITE_PROTECT: + return EROFS; + case ERROR_SETMARK_DETECTED: + case ERROR_BEGINNING_OF_MEDIA: + return ESPIPE; + case ERROR_NOT_SAME_DEVICE: + return EXDEV; + } + return ENOSYS; +} + +#endif + diff --git a/src/win32_util.h b/src/win32_util.h new file mode 100644 index 0000000..9e1e329 --- /dev/null +++ b/src/win32_util.h @@ -0,0 +1,50 @@ +/* win32_util.h + * + * This file is part of vchanger by Josh Fisher. + * + * vchanger copyright (C) 2008-2013 Josh Fisher + * + * vchanger is free software. + * You may redistribute it and/or modify it under the terms of the + * GNU General Public License version 2, as published by the Free + * Software Foundation. + * + * vchanger 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 vchanger. See the file "COPYING". If not, + * write to: The Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. +*/ + +#ifndef COMPAT_UTIL_H_ +#define COMPAT_UTIL_H_ + +#ifdef HAVE_WINDOWS_H + +/* Some utility functions needed for Windows version */ + +/* number of 100 ns intervals between FILETIME epoch and Unix epoch */ +#define EPOCH_FILETIME (116444736000000000LL) + +#ifdef __cplusplus +extern "C" { +#endif + +time_t ftime2utime(const FILETIME *time); +wchar_t* AnsiToUTF16(const char *str, wchar_t **u16str, size_t *u16size); +char *UTF16ToAnsi(const wchar_t *u16str, char **str, size_t *str_size); +int w32errno(DWORD werr); + +#ifdef __cplusplus +} +#endif + +#endif + + +#endif /* _COMPAT_UTIL_H */ diff --git a/win32/installer.nsi b/win32/installer.nsi new file mode 100644 index 0000000..85e8363 --- /dev/null +++ b/win32/installer.nsi @@ -0,0 +1,150 @@ +#................- +#. Date of creation: 2015-06-01 +#. Name: installer.nsi +#................- +#..- Package parameters ... +SetCompress force +SetCompressor lzma +!include LogicLib.nsh +!include MUI2.nsh +!include WinMessages.nsh +!include x64.nsh +!insertmacro MUI_LANGUAGE English +#... Installation Windows Parameters .. +!define APPNAME "vchanger" +!define COMPANYNAME "Josh Fisher" +!define DESCRIPTION "A virtual disk autochanger for Bacula" +# These three must be integers +!define VERSIONMAJOR 1 +!define VERSIONMINOR 0 +!define VERSIONBUILD 1 +# These will be displayed by the "Click here for support information" link in "Add/Remove Programs" +!define HELPURL "http://sourceforge.net/projects/vchanger/" # "Support Information" link +Name "vchanger 1.0.1" +VIProductVersion "1.0.1.0" +VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "vchanger Installer" +VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "Copyright (c) Josh Fisher 2008-2015" +VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "vchanger Windows Installer" +VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "1.0.1" +ShowInstDetails nevershow +SilentInstall normal +RequestExecutionLevel admin +AutoCloseWindow True +OutFile "vchanger-1.0.1.exe" + +PageEx license + LicenseData "license.txt" +PageExEnd +Page directory +Page instfiles + +UninstPage uninstConfirm +UninstPage instfiles + +Section "vchanger 32-bit" SEC0001 + SectionIn RO + SetOutPath $INSTDIR + ClearErrors + CreateDirectory "$APPDATA\vchanger" + IfErrors 0 +3 + MessageBox MB_OK 'Could not create vchanger work directory' + Quit + File license.txt + File ReleaseNotes.txt + File vchangerHowto.html + File vchanger-example.conf + File vchanger.exe + WriteUninstaller "uninstall.exe" + IfFileExists "$APPDATA\vchanger\vchanger.conf" +2 0 + CopyFiles "$INSTDIR\vchanger-example.conf" "$APPDATA\vchanger\vchanger.conf" + WriteRegStr HKLM "Software\vchanger" "Install_Dir" "$INSTDIR" + ; Write the uninstall keys for Windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "DisplayName" "vchanger" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "NoRepair" 1 + CreateDirectory "$SMPROGRAMS\vchanger" + CreateShortCut "$SMPROGRAMS\vchanger\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\vchanger\vchanger Howto.lnk" "$INSTDIR\vchangerHowto.html" "" "$INSTDIR\vchangerHowto.html" 0 + CreateShortcut "$SMPROGRAMS\vchanger\vchanger config.lnk" "$PROGRAMFILES32\Windows NT\Accessories\wordpad.exe" "$APPDATA\vchanger\vchanger.conf" +SectionEnd + +Section "vchanger 64-bit" SEC0002 + SectionIn RO + SetOutPath $INSTDIR + ClearErrors + CreateDirectory "$APPDATA\vchanger" + IfErrors 0 +3 + MessageBox MB_OK 'Could not create vchanger work directory' + Quit + File license.txt + File ReleaseNotes.txt + File vchangerHowto.html + File vchanger-example.conf + File "/oname=vchanger.exe" vchanger64.exe + WriteUninstaller "uninstall.exe" + IfFileExists "$APPDATA\vchanger\vchanger.conf" +2 0 + CopyFiles "$INSTDIR\vchanger-example.conf" "$APPDATA\vchanger\vchanger.conf" + WriteRegStr HKLM "Software\vchanger" "Install_Dir" "$INSTDIR" + ; Write the uninstall keys for Windows + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "DisplayName" "vchanger" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "UninstallString" '"$INSTDIR\uninstall.exe"' + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" "NoRepair" 1 + CreateDirectory "$SMPROGRAMS\vchanger" + CreateShortCut "$SMPROGRAMS\vchanger\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 + CreateShortCut "$SMPROGRAMS\vchanger\vchanger Howto.lnk" "$INSTDIR\vchangerHowto.html" "" "$INSTDIR\vchangerHowto.html" 0 + CreateShortcut "$SMPROGRAMS\vchanger\vchanger config.lnk" "$PROGRAMFILES64\Windows NT\Accessories\wordpad.exe" "$APPDATA\vchanger\vchanger.conf" +SectionEnd + +# Uninstaller Section +Section "Uninstall" + # Remove shortcuts, if any + Delete "$SMPROGRAMS\vchanger\*.*" + RMDir "$SMPROGRAMS\vchanger" + + # Remove files and uninstaller + Delete $INSTDIR\vchanger.exe + Delete $INSTDIR\license.txt + Delete $INSTDIR\ReleaseNotes.txt + Delete $INSTDIR\vchangerHowto.html + Delete $INSTDIR\vchanger-example.conf + Delete $INSTDIR\uninstall.exe + RMDir "$INSTDIR" + + # Remove information from the registry + DeleteRegKey HKLM "Software\vchanger" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\vchanger" +SectionEnd + +Function .onInit + SetShellVarContext all + #Determine the bitness of the OS and enable the correct section + ${If} ${RunningX64} + SectionSetFlags SEC0001 ${SECTION_OFF} + SectionSetFlags SEC0002 ${SF_SELECTED} + StrCpy $INSTDIR "$PROGRAMFILES64\vchanger" + SetRegView 64 + ${Else} + SectionSetFlags SEC0002 ${SECTION_OFF} + SectionSetFlags SEC0001 ${SF_SELECTED} + StrCpy $INSTDIR "$PROGRAMFILES32\vchanger" + SetRegView 32 + ${EndIf} +FunctionEnd + +Function un.onInit + SetShellVarContext all + #Determine the bitness of the OS and enable the correct section + ${If} ${RunningX64} + StrCpy $INSTDIR "$PROGRAMFILES64\vchanger" + SetRegView 64 + ${Else} + StrCpy $INSTDIR "$PROGRAMFILES32\vchanger" + SetRegView 32 + ${EndIf} +FunctionEnd + +Function .onInstSuccess + MessageBox MB_OK "You have successfully installed vchanger." +FunctionEnd diff --git a/win32build b/win32build new file mode 100755 index 0000000..157c50a --- /dev/null +++ b/win32build @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Build for 32-bit and 64-bit Windows binary and create NSIS installer +# +VERS=1.0.1 +rm -f ./win32/vchanger-$VERS.exe +rm -f ./win32/vchanger.exe +rm -f ./win32/vchanger64.exe +rm -f ./win32/vchanger-example.conf +rm -f ./win32/vchangerHowto.htm +rm -f ./win32/license.txt +rm -f ./win32/ReleaseNotes.txt +rm -rf /tmp/vchanger-win32 +mkdir /tmp/vchanger-win32 +make distclean + +# +# Configure for Linux mingw cross-compile and build 32-bit Windows binary +# +./configure --host=i686-w64-mingw32 --build=`./config.guess` --prefix=/tmp/vchanger-win32 +[ $? -eq 0 ] || exit 1 +make +[ $? -eq 0 ] || exit 1 +make install-strip +[ $? -eq 0 ] || exit 1 +cp /tmp/vchanger-win32/bin/vchanger.exe ./win32 + +# +# Configure for Linux mingw cross-compile and build 64-bit Windows binary +# +make distclean +rm -rf /tmp/vchanger-win32/* +./configure --host=x86_64-w64-mingw32 --build=`./config.guess` --prefix=/tmp/vchanger-win32 +[ $? -eq 0 ] || exit 1 +make +[ $? -eq 0 ] || exit 1 +make install-strip +[ $? -eq 0 ] || exit 1 +cp /tmp/vchanger-win32/bin/vchanger.exe ./win32/vchanger64.exe +cp /tmp/vchanger-win32/share/doc/vchanger-$VERS/vchanger-example.conf ./win32 +cp /tmp/vchanger-win32/share/doc/vchanger-$VERS/vchangerHowto.html ./win32 +cp COPYING ./win32/license.txt +cp ReleaseNotes ./win32/ReleaseNotes.txt +rm -rf /tmp/vchanger-win32 + +# +# Create NSIS installer +# +cd win32 +makensis installer.nsi +chmod 755 vchanger-$VERS.exe +cd ..