mirror of
https://github.com/wanderleihuttel/vchanger.git
synced 2026-08-07 16:36:11 +00:00
Import project from sourceforge.net
This commit is contained in:
@@ -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:
|
||||||
@@ -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.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 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.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
@@ -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
|
||||||
@@ -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.
|
||||||
+13
@@ -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
|
||||||
+817
@@ -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:
|
||||||
@@ -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.
|
||||||
|
|
||||||
+254
@@ -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:
|
||||||
|
|
||||||
|
=================================================================
|
||||||
|
|
||||||
Vendored
+1039
File diff suppressed because it is too large
Load Diff
+1558
File diff suppressed because it is too large
Load Diff
+310
@@ -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 <alloca.h> 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 <ctype.h> header file. */
|
||||||
|
#undef HAVE_CTYPE_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <dirent.h> 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 <errno.h> header file. */
|
||||||
|
#undef HAVE_ERRNO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <fcntl.h> 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 <getopt.h> 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 <grp.h> header file. */
|
||||||
|
#undef HAVE_GRP_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <io.h> header file. */
|
||||||
|
#undef HAVE_IO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libgen.h> header file. */
|
||||||
|
#undef HAVE_LIBGEN_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <libudev.h> header file. */
|
||||||
|
#undef HAVE_LIBUDEV_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <limits.h> header file. */
|
||||||
|
#undef HAVE_LIMITS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <locale.h> 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 <memory.h> header file. */
|
||||||
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <mntent.h> header file. */
|
||||||
|
#undef HAVE_MNTENT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||||
|
#undef HAVE_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <optarg.h> 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 <pthread.h> header file. */
|
||||||
|
#undef HAVE_PTHREAD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pwd.h> 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 <signal.h> 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 <stdarg.h> 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 <stddef.h> header file. */
|
||||||
|
#undef HAVE_STDDEF_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdio.h> header file. */
|
||||||
|
#undef HAVE_STDIO_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <strings.h> header file. */
|
||||||
|
#undef HAVE_STRINGS_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <string.h> 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 <syslog.h> header file. */
|
||||||
|
#undef HAVE_SYSLOG_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/bitypes.h> header file. */
|
||||||
|
#undef HAVE_SYS_BITYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/mount.h> header file. */
|
||||||
|
#undef HAVE_SYS_MOUNT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||||
|
*/
|
||||||
|
#undef HAVE_SYS_NDIR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
|
#undef HAVE_SYS_PARAM_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||||
|
#undef HAVE_SYS_SELECT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||||
|
#undef HAVE_SYS_STAT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/timespec.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIMESPEC_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
|
#undef HAVE_SYS_TIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
|
#undef HAVE_SYS_TYPES_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/ucred.h> header file. */
|
||||||
|
#undef HAVE_SYS_UCRED_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||||
|
#undef HAVE_SYS_WAIT_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <time.h> 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 <unistd.h> header file. */
|
||||||
|
#undef HAVE_UNISTD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <utime.h> header file. */
|
||||||
|
#undef HAVE_UTIME_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <varargs.h> 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 <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> 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 <sys/synch.h>,
|
||||||
|
<pthread.h>, or <semaphore.h> 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 <sys/types.h> 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 <sys/types.h> does not define. */
|
||||||
|
#undef mode_t
|
||||||
|
|
||||||
|
/* Define to `long int' if <sys/types.h> does not define. */
|
||||||
|
#undef off_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef pid_t
|
||||||
|
|
||||||
|
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||||
|
#undef size_t
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
|
#undef ssize_t
|
||||||
|
|
||||||
|
/* Define to __typeof__ if your compiler spells it that way. */
|
||||||
|
#undef typeof
|
||||||
|
|
||||||
|
/* Define to `int' if <sys/types.h> 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
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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 <windows.h>])
|
||||||
|
AC_CHECK_HEADER([winsock.h], [AC_DEFINE([HAVE_WINSOCK_H],,[have header winsock.h])], [], [#include <windows.h>])
|
||||||
|
AC_CHECK_HEADER([winreg.h], [AC_DEFINE([HAVE_WINREG_H],,[have header winreg.h])], [], [#include <windows.h>])
|
||||||
|
AC_CHECK_HEADER([shlobj.h], [AC_DEFINE([HAVE_SHLOBJ_H],,[have header shlobj.h])], [], [#include <windows.h>])
|
||||||
|
# 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
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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 <oliva@dcc.unicamp.br>.
|
||||||
|
|
||||||
|
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 <bug-automake@gnu.org>.
|
||||||
|
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:
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
man8_MANS = vchanger.8
|
||||||
|
man5_MANS = vchanger.conf.5
|
||||||
+509
@@ -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:
|
||||||
@@ -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"
|
||||||
@@ -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"
|
||||||
+206
@@ -0,0 +1,206 @@
|
|||||||
|
'\" t
|
||||||
|
.\" Title: vchanger
|
||||||
|
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
||||||
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
|
.\" 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
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
VCHANGER(8)
|
||||||
|
===========
|
||||||
|
Josh Fisher <jfisher@jaybus.com>
|
||||||
|
: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.
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
'\" t
|
||||||
|
.\" Title: vchanger.conf
|
||||||
|
.\" Author: Josh Fisher <jfisher@jaybus.com>
|
||||||
|
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
|
||||||
|
.\" 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
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
VCHANGER.CONF(5)
|
||||||
|
================
|
||||||
|
Josh Fisher <jfisher@jaybus.com>
|
||||||
|
: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.
|
||||||
File diff suppressed because it is too large
Load Diff
Executable
+527
@@ -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:
|
||||||
@@ -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 <pinard@iro.umontreal.ca>, 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# 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 <bug-automake@gnu.org>."
|
||||||
|
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:
|
||||||
@@ -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 <jfisher@jaybus.com>
|
||||||
|
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 <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.1
|
||||||
|
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Initial spec file
|
||||||
@@ -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 <jfisher@jaybus.com>
|
||||||
|
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 <jfisher@jaybus.com>
|
||||||
|
- Updated to release 1.0.1
|
||||||
|
* Fri Apr 3 2015 Josh Fisher <jfisher@jaybus.com>
|
||||||
|
- Initial spec file
|
||||||
@@ -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
|
||||||
@@ -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:
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
} &
|
||||||
@@ -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
|
||||||
|
} &
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
MOUNT_DIR=/mnt/vchanger
|
||||||
|
MOUNT_OPTIONS=
|
||||||
@@ -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
|
||||||
+722
@@ -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:
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
#include <sys/select.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#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
|
||||||
|
}
|
||||||
@@ -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_ */
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDDEF_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DIRENT_H
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#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<tString> vname;
|
||||||
|
std::list<tString>::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <vector>
|
||||||
|
#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<MagazineSlot> 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<MagazineState> 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<VirtualSlot> 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<DriveState> DriveStateArray;
|
||||||
|
|
||||||
|
#endif /*CHANGERSTATE_H_*/
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#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
|
||||||
@@ -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 */
|
||||||
@@ -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 <windows.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAV_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#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
|
||||||
@@ -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 */
|
||||||
@@ -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 <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#include "compat/getuid.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emulate GNU extension function getline().
|
||||||
|
*/
|
||||||
|
uid_t getuid()
|
||||||
|
{
|
||||||
|
return 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
gid_t getgid()
|
||||||
|
{
|
||||||
|
return 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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 */
|
||||||
@@ -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 <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#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
|
||||||
@@ -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_ */
|
||||||
@@ -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 <windows.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDDEF_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#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
|
||||||
@@ -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 */
|
||||||
@@ -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
|
||||||
@@ -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 */
|
||||||
@@ -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 <windows.h>
|
||||||
|
#include "win32_util.h"
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#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
|
||||||
@@ -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 */
|
||||||
@@ -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 <stdarg.h>
|
||||||
|
#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
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DIRENT_H
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
@@ -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_*/
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_VARARGS_H
|
||||||
|
#include <varargs.h>
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -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_ */
|
||||||
+1185
File diff suppressed because it is too large
Load Diff
+190
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INIPARSE_H_
|
||||||
|
#define _INIPARSE_H_ 1
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#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<IniValuePair> 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_ */
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "compat_defs.h"
|
||||||
|
#ifdef HAVE_STDIO_H
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LOGHANDLER_H_
|
||||||
|
#define _LOGHANDLER_H_ 1
|
||||||
|
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
#include <syslog.h>
|
||||||
|
#else
|
||||||
|
#include "compat/syslog.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PTHREAD_H
|
||||||
|
#include <pthread.h>
|
||||||
|
#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_ */
|
||||||
+726
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIMITS_H
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_ */
|
||||||
@@ -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
|
||||||
+476
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#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
|
||||||
|
* <other> 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;
|
||||||
|
}
|
||||||
@@ -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 <string>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
typedef std::basic_string<char> tString;
|
||||||
|
typedef tString::iterator tStringIterator;
|
||||||
|
typedef tString::const_iterator tStringConstIterator;
|
||||||
|
typedef tString::reverse_iterator tStringReverseIterator;
|
||||||
|
typedef tString::const_reverse_iterator tStringConstReverseIterator;
|
||||||
|
typedef std::list<tString> tStringList;
|
||||||
|
typedef tStringList::iterator tStringListIterator;
|
||||||
|
typedef tStringList::const_iterator tStringListConstIterator;
|
||||||
|
typedef tStringList::reverse_iterator tStringListReverseIterator;
|
||||||
|
typedef tStringList::const_reverse_iterator tStringListConstReverseIterator;
|
||||||
|
typedef std::vector<tString> tStringArray;
|
||||||
|
typedef std::map<tString, tString> tStringMap;
|
||||||
|
typedef std::map<tString, tStringList> 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
|
||||||
+192
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GRP_H
|
||||||
|
#include <grp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PWD_H
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TIME_H
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
+33
@@ -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_ */
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "uuidlookup.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
|
||||||
|
#include "targetver.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
#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 <mntent.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 <sys/param.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_MOUNT_H
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_UCRED_H
|
||||||
|
#include <sys/ucred.h>
|
||||||
|
#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 <libudev.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 <blkid/blkid.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 <stdio.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GETOPT_H
|
||||||
|
#include <getopt.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CTYPE_H
|
||||||
|
#include <ctype.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LOCALE_H
|
||||||
|
#include <locale.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SIGNAL_H
|
||||||
|
#include <signal.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
+309
@@ -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 <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
#include <syslog.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#include "targetver.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
#include <direct.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
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
+70
@@ -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_ */
|
||||||
@@ -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 <windows.h>
|
||||||
|
#include <winerror.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#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
|
||||||
|
|
||||||
@@ -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 */
|
||||||
@@ -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
|
||||||
Executable
+52
@@ -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 ..
|
||||||
Reference in New Issue
Block a user