From: Arvin Schnell Date: Mon, 10 Jan 2011 15:36:57 +0000 (+0100) Subject: - first steps handling snapshot info files X-Git-Tag: v0.1.3~559 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ea71856242022cf3c0c1f4b243aad50c4cdb65f7;p=thirdparty%2Fsnapper.git - first steps handling snapshot info files --- diff --git a/.gitignore b/.gitignore index 89620f31..e67cdafb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,14 @@ -BUILD +Makefile.in +Makefile +.deps +.libs +aclocal.m4 +autom4te.cache +config.* +configure +depcomp +install-sh +libtool +ltmain.sh +missing +stamp-h1 diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..3be27c9b --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Arvin Schnell diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..d511905c --- /dev/null +++ b/COPYING @@ -0,0 +1,339 @@ + 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 Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..7ba43499 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,23 @@ +# +# Makefile.am for snapper +# + +SUBDIRS = snapper examples + +AUTOMAKE_OPTIONS = foreign dist-bzip2 no-dist-gzip + +doc_DATA = AUTHORS COPYING + +EXTRA_DIST = $(doc_DATA) VERSION + + +snapper-$(VERSION).tar.bz2: dist-bzip2 + +package-local: snapper-$(VERSION).tar.bz2 + rm -f package/snapper-*.tar.bz2 + rm -f package/*~ + rm -f package/*.bak + mv snapper-$(VERSION).tar.bz2 package/ + +package: package-local + diff --git a/Makefile.repo b/Makefile.repo new file mode 100644 index 00000000..81d7c30c --- /dev/null +++ b/Makefile.repo @@ -0,0 +1,20 @@ +# +# Makefile.repo for libsnapper +# + +configure: all + ./configure + +all: + aclocal + autoconf + autoheader + autoreconf --force --install + +install: configure + make + make install + +reconf: all + ./config.status --recheck + ./config.status diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..8acdd82b --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.0.1 diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..4899caae --- /dev/null +++ b/configure.in @@ -0,0 +1,36 @@ + +AC_INIT(snapper/Snapper.h) + +VERSION=`cat ./VERSION` + +AM_INIT_AUTOMAKE(snapper, $VERSION) +AM_CONFIG_HEADER(config.h) + +AC_DISABLE_STATIC + +AC_PROG_CXX +AC_PROG_LIBTOOL +AM_PROG_LIBTOOL + +AC_PREFIX_DEFAULT(/usr) + +dnl Automake 1.11 enables silent compilation +dnl Disable it by "configure --disable-silent-rules" or "make V=1" +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +CFLAGS="${CFLAGS} -Wall -Wformat=2 -Wmissing-prototypes" +CXXFLAGS="${CXXFLAGS} -std=c++0x -DHAVE_CXX0X -Wall -Wextra -Wformat=2 -Wnon-virtual-dtor -Wno-unused-parameter" + +docdir=\${prefix}/share/doc/packages/snapper +fillupdir=/var/adm/fillup-templates + +AC_SUBST(VERSION) +AC_SUBST(docdir) +AC_SUBST(fillupdir) + +AC_OUTPUT( + Makefile + snapper/Makefile + examples/Makefile + package/snapper.spec:snapper.spec.in +) diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 00000000..648188c8 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,4 @@ +List.o +List +Create.o +Create diff --git a/examples/Create.cc b/examples/Create.cc new file mode 100644 index 00000000..2c1e9f0c --- /dev/null +++ b/examples/Create.cc @@ -0,0 +1,22 @@ + +#include +#include + +#include + +using namespace snapper; +using namespace std; + +int +main(int argc, char** argv) +{ + createSingleSnapshot("test"); + + unsigned int pre_id = createPreSnapshot("test undo"); + + createPostSnapshot(pre_id); + + listSnapshots(); + + exit(EXIT_SUCCESS); +} diff --git a/examples/List.cc b/examples/List.cc new file mode 100644 index 00000000..2f9758d3 --- /dev/null +++ b/examples/List.cc @@ -0,0 +1,16 @@ + +#include +#include + +#include + +using namespace snapper; +using namespace std; + +int +main(int argc, char** argv) +{ + listSnapshots(); + + exit(EXIT_SUCCESS); +} diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 00000000..d8df7443 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,23 @@ +# +# Makefile.am for libsnapper/examples +# + +INCLUDES = -I$(top_srcdir) + +LDADD = ../snapper/libsnapper.la + +noinst_PROGRAMS = List Create + +List_SOURCES = List.cc + +Create_SOURCES = Create.cc + +exampledir = $(docdir)/examples + +example_DATA = List.cc Create.cc + +EXTRA_DIST = $(example_DATA) Makefile.example + +install-data-local: + /usr/bin/install -d -p -m 755 $(DESTDIR)$(exampledir) + /usr/bin/install -p -m 644 Makefile.example $(DESTDIR)$(exampledir)/Makefile diff --git a/examples/Makefile.example b/examples/Makefile.example new file mode 100644 index 00000000..945db75e --- /dev/null +++ b/examples/Makefile.example @@ -0,0 +1,33 @@ + +PROGRAMS = TestDisk TestDiskLog TestProbing TestLvm TestMd TestLoop \ + SaveGraph ShowBytes + +all: $(PROGRAMS) + +TestDisk: TestDisk.cc + g++ $< -o $@ -Wall -O2 -lstorage + +TestDiskLog: TestDiskLog.cc + g++ $< -o $@ -Wall -O2 -lstorage + +TestProbing: TestProbing.cc + g++ $< -o $@ -Wall -O2 -lstorage + +TestLvm: TestLvm.cc + g++ $< -o $@ -Wall -O2 -lstorage + +TestMd: TestMd.cc + g++ $< -o $@ -Wall -O2 -lstorage + +TestLoop: TestLoop.cc + g++ $< -o $@ -Wall -O2 -lstorage + +SaveGraph: SaveGraph.cc + g++ $< -o $@ -Wall -O2 -lstorage + +ShowBytes: ShowBytes.cc + g++ $< -o $@ -Wall -O2 -lstorage + +clean: + rm $(PROGRAMS) + diff --git a/package/.gitignore b/package/.gitignore new file mode 100644 index 00000000..c29f158b --- /dev/null +++ b/package/.gitignore @@ -0,0 +1,2 @@ +snapper-*.tar.bz2 +snapper.spec diff --git a/package/snapper.changes b/package/snapper.changes index e69de29b..07ec0fa7 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -0,0 +1,5 @@ +------------------------------------------------------------------- +Mon Jan 10 14:55:25 CET 2011 - aschnell@suse.de + +- started development + diff --git a/package/snapper.spec b/package/snapper.spec new file mode 100644 index 00000000..cda500a8 --- /dev/null +++ b/package/snapper.spec @@ -0,0 +1,98 @@ +# +# spec file for package snapper (Version 0.0.1) +# +# norootforbuild + +Name: snapper +Version: 0.0.1 +Release: 0 +License: GPL +Group: System/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Source: snapper-%{version}.tar.bz2 +Source1: snapper-rpmlintrc + +prefix: /usr + +BuildRequires: gcc-c++ boost-devel blocxx-devel doxygen dejagnu libxml2-devel + +Requires: btrfs-progs + +PreReq: %fillup_prereq +Summary: Library for snapper management + +%description +This package contains snapper, a library for filesystem snapshot management. + +Authors: +-------- + Arvin Schnell + +%prep +%setup -n snapper-%{version} + +%build +export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG" +export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG" + +aclocal +libtoolize --force --automake --copy +autoheader +automake --add-missing --copy +autoconf + +%{?suse_update_config:%{suse_update_config -f}} +./configure --libdir=%{_libdir} --prefix=%{prefix} --mandir=%{_mandir} --disable-silent-rules +make %{?jobs:-j%jobs} + +%check +LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale make check + +%install +make install DESTDIR="$RPM_BUILD_ROOT" + +install -d -m 755 $RPM_BUILD_ROOT/var/lock/snapper + +%{find_lang} snapper + +%clean +rm -rf "$RPM_BUILD_ROOT" + +%files -f snapper.lang +%defattr(-,root,root) +%{_libdir}/libsnapper.so.* +%dir /var/lock/libsnapper +/var/adm/fillup-templates/sysconfig.snapper-libsnapper +%doc %dir %{prefix}/share/doc/packages/libsnapper +%doc %{prefix}/share/doc/packages/snapper/AUTHORS +%doc %{prefix}/share/doc/packages/snapper/COPYING + +%post +/sbin/ldconfig +%{fillup_only -an snapper} + +%postun +/sbin/ldconfig + +%package devel +Requires: libsnapper = %version +Requires: gcc-c++ libstdc++-devel boost-devel blocxx-devel libxml2-devel +Summary: Header files and documentation for libsnapper +Group: Development/Languages/C and C++ + +%description devel +This package contains header files and documentation for developing with +libsnapper. + +Authors: +-------- + Arvin Schnell + +%files devel +%defattr(-,root,root) +%{_libdir}/libsnapper.la +%{_libdir}/libsnapper.so +%{prefix}/include/snapper +%doc %{prefix}/share/doc/packages/libsnapper/autodocs +%doc %{prefix}/share/doc/packages/libsnapper/examples + diff --git a/snapper.spec.in b/snapper.spec.in new file mode 100644 index 00000000..804799a8 --- /dev/null +++ b/snapper.spec.in @@ -0,0 +1,98 @@ +# +# spec file for package snapper (Version @VERSION@) +# +# norootforbuild + +Name: snapper +Version: @VERSION@ +Release: 0 +License: GPL +Group: System/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Source: snapper-%{version}.tar.bz2 +Source1: snapper-rpmlintrc + +prefix: /usr + +BuildRequires: gcc-c++ boost-devel blocxx-devel doxygen dejagnu libxml2-devel + +Requires: btrfs-progs + +PreReq: %fillup_prereq +Summary: Library for snapper management + +%description +This package contains snapper, a library for filesystem snapshot management. + +Authors: +-------- + Arvin Schnell + +%prep +%setup -n snapper-%{version} + +%build +export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG" +export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG" + +aclocal +libtoolize --force --automake --copy +autoheader +automake --add-missing --copy +autoconf + +%{?suse_update_config:%{suse_update_config -f}} +./configure --libdir=%{_libdir} --prefix=%{prefix} --mandir=%{_mandir} --disable-silent-rules +make %{?jobs:-j%jobs} + +%check +LOCALEDIR=$RPM_BUILD_ROOT/usr/share/locale make check + +%install +make install DESTDIR="$RPM_BUILD_ROOT" + +install -d -m 755 $RPM_BUILD_ROOT/var/lock/snapper + +%{find_lang} snapper + +%clean +rm -rf "$RPM_BUILD_ROOT" + +%files -f snapper.lang +%defattr(-,root,root) +%{_libdir}/libsnapper.so.* +%dir /var/lock/libsnapper +/var/adm/fillup-templates/sysconfig.snapper-libsnapper +%doc %dir %{prefix}/share/doc/packages/libsnapper +%doc %{prefix}/share/doc/packages/snapper/AUTHORS +%doc %{prefix}/share/doc/packages/snapper/COPYING + +%post +/sbin/ldconfig +%{fillup_only -an snapper} + +%postun +/sbin/ldconfig + +%package devel +Requires: libsnapper = %version +Requires: gcc-c++ libstdc++-devel boost-devel blocxx-devel libxml2-devel +Summary: Header files and documentation for libsnapper +Group: Development/Languages/C and C++ + +%description devel +This package contains header files and documentation for developing with +libsnapper. + +Authors: +-------- + Arvin Schnell + +%files devel +%defattr(-,root,root) +%{_libdir}/libsnapper.la +%{_libdir}/libsnapper.so +%{prefix}/include/snapper +%doc %{prefix}/share/doc/packages/libsnapper/autodocs +%doc %{prefix}/share/doc/packages/libsnapper/examples + diff --git a/snapper/.gitignore b/snapper/.gitignore new file mode 100644 index 00000000..66a3f3fe --- /dev/null +++ b/snapper/.gitignore @@ -0,0 +1,2 @@ +*.lo +*.la diff --git a/snapper/AppUtil.cc b/snapper/AppUtil.cc new file mode 100644 index 00000000..fdccfefc --- /dev/null +++ b/snapper/AppUtil.cc @@ -0,0 +1,401 @@ +/* + * Copyright (c) [2004-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "snapper/AppUtil.h" + + +namespace snapper +{ + using namespace std; + + +void createPath(const string& Path_Cv) +{ + string::size_type Pos_ii = 0; + while ((Pos_ii = Path_Cv.find('/', Pos_ii + 1)) != string::npos) + { + string Tmp_Ci = Path_Cv.substr(0, Pos_ii); + mkdir(Tmp_Ci.c_str(), 0777); + } + mkdir(Path_Cv.c_str(), 0777); +} + + +bool +checkDir(const string& Path_Cv) +{ + struct stat Stat_ri; + + return (stat(Path_Cv.c_str(), &Stat_ri) >= 0 && + S_ISDIR(Stat_ri.st_mode)); +} + + +bool +getStatMode(const string& Path_Cv, mode_t& val ) +{ + struct stat Stat_ri; + int ret_ii = stat(Path_Cv.c_str(), &Stat_ri); + + if( ret_ii==0 ) + val = Stat_ri.st_mode; + else + y2mil( "stat " << Path_Cv << " ret:" << ret_ii ); + + return (ret_ii==0); +} + +bool +setStatMode(const string& Path_Cv, mode_t val ) +{ + int ret_ii = chmod( Path_Cv.c_str(), val ); + if( ret_ii!=0 ) + y2mil( "chmod " << Path_Cv << " ret:" << ret_ii ); + return( ret_ii==0 ); +} + + +bool +checkNormalFile(const string& Path_Cv) +{ + struct stat Stat_ri; + + return (stat(Path_Cv.c_str(), &Stat_ri) >= 0 && + S_ISREG(Stat_ri.st_mode)); +} + + + list + glob(const string& path, int flags) + { + list ret; + + glob_t globbuf; + if (glob(path.c_str(), flags, 0, &globbuf) == 0) + { + for (char** p = globbuf.gl_pathv; *p != 0; p++) + ret.push_back(*p); + } + globfree (&globbuf); + + return ret; + } + + +static const blocxx::String component = "libsnapper"; + + +void createLogger(const string& name, const string& logpath, const string& logfile) +{ + using namespace blocxx; + + if (logpath != "NULL" && logfile != "NULL") + { + String nm = name.c_str(); + LoggerConfigMap configItems; + LogAppenderRef logApp; + if (logpath != "STDERR" && logfile != "STDERR" && + logpath != "SYSLOG" && logfile != "SYSLOG") + { + String StrKey; + String StrPath; + StrKey.format("log.%s.location", name.c_str()); + StrPath = (logpath + "/" + logfile).c_str(); + configItems[StrKey] = StrPath; + logApp = + LogAppender::createLogAppender(nm, LogAppender::ALL_COMPONENTS, + LogAppender::ALL_CATEGORIES, + "%d %-5p %c(%P) %F(%M):%L - %m", + LogAppender::TYPE_FILE, + configItems); + } + else if (logpath == "STDERR" && logfile == "STDERR") + { + logApp = + LogAppender::createLogAppender(nm, LogAppender::ALL_COMPONENTS, + LogAppender::ALL_CATEGORIES, + "%d %-5p %c(%P) %F(%M):%L - %m", + LogAppender::TYPE_STDERR, + configItems); + } + else + { + logApp = + LogAppender::createLogAppender(nm, LogAppender::ALL_COMPONENTS, + LogAppender::ALL_CATEGORIES, + "%d %-5p %c(%P) %F(%M):%L - %m", + LogAppender::TYPE_SYSLOG, + configItems); + } + + LogAppender::setDefaultLogAppender(logApp); + } +} + + +bool +testLogLevel(LogLevel level) +{ + using namespace blocxx; + + ELogLevel curLevel = LogAppender::getCurrentLogAppender()->getLogLevel(); + + switch (level) + { + case DEBUG: + return curLevel >= ::blocxx::E_DEBUG_LEVEL; + case MILESTONE: + return curLevel >= ::blocxx::E_INFO_LEVEL; + case WARNING: + return curLevel >= ::blocxx::E_WARNING_LEVEL; + case ERROR: + return curLevel >= ::blocxx::E_ERROR_LEVEL; + default: + return curLevel >= ::blocxx::E_FATAL_ERROR_LEVEL; + } +} + + +void +prepareLogStream(ostringstream& stream) +{ + stream.imbue(std::locale::classic()); + stream.setf(std::ios::boolalpha); + stream.setf(std::ios::showbase); +} + + +ostringstream* +logStreamOpen() +{ + std::ostringstream* stream = new ostringstream; + prepareLogStream(*stream); + return stream; +} + + +void +logStreamClose(LogLevel level, const char* file, unsigned line, const char* func, + ostringstream* stream) +{ + using namespace blocxx; + + ELogLevel curLevel = LogAppender::getCurrentLogAppender()->getLogLevel(); + String category; + + switch (level) + { + case DEBUG: + if (curLevel >= ::blocxx::E_DEBUG_LEVEL) + category = Logger::STR_DEBUG_CATEGORY; + break; + case MILESTONE: + if (curLevel >= ::blocxx::E_INFO_LEVEL) + category = Logger::STR_INFO_CATEGORY; + break; + case WARNING: + if (curLevel >= ::blocxx::E_WARNING_LEVEL) + category = Logger::STR_WARNING_CATEGORY; + break; + case ERROR: + if (curLevel >= ::blocxx::E_ERROR_LEVEL) + category = Logger::STR_ERROR_CATEGORY; + break; + default: + if (curLevel >= ::blocxx::E_FATAL_ERROR_LEVEL) + category = Logger::STR_FATAL_CATEGORY; + break; + } + + if (!category.empty()) + { + string tmp = stream->str(); + + string::size_type pos1 = 0; + + while (true) + { + string::size_type pos2 = tmp.find('\n', pos1); + + if (pos2 != string::npos || pos1 != tmp.length()) + LogAppender::getCurrentLogAppender()->logMessage(LogMessage(component, category, + String(tmp.substr(pos1, pos2 - pos1)), + file, line, func)); + + if (pos2 == string::npos) + break; + + pos1 = pos2 + 1; + } + } + + delete stream; +} + + +bool +readlink(const string& path, string& buf) +{ + char tmp[1024]; + int count = ::readlink(path.c_str(), tmp, sizeof(tmp)); + if (count >= 0) + buf = string(tmp, count); + return count != -1; +} + + + bool + readlinkat(int fd, const string& path, string& buf) + { + char tmp[1024]; + int count = ::readlinkat(fd, path.c_str(), tmp, sizeof(tmp)); + if (count >= 0) + buf = string(tmp, count); + return count != -1; + } + + + void + Text::clear() + { + native.clear(); + text.clear(); + } + + + const Text& + Text::operator+=(const Text& a) + { + native += a.native; + text += a.text; + return *this; + } + + + string + sformat(const string& format, va_list ap) + { + char* result; + + if (vasprintf(&result, format.c_str(), ap) == -1) + return string(); + + string str(result); + free(result); + return str; + } + + + Text + sformat(const Text& format, ...) + { + Text text; + va_list ap; + + va_start(ap, format); + text.native = sformat(format.native, ap); + va_end(ap); + + va_start(ap, format); + text.text = sformat(format.text, ap); + va_end(ap); + + return text; + } + + + Text _(const char* msgid) + { + return Text(msgid, dgettext("libsnapper", msgid)); + } + + Text _(const char* msgid, const char* msgid_plural, unsigned long int n) + { + return Text(n == 1 ? msgid : msgid_plural, dngettext("libsnapper", msgid, msgid_plural, n)); + } + + + string + hostname() + { + struct utsname buf; + if (uname(&buf) != 0) + return string("unknown"); + string hostname(buf.nodename); + if (strlen(buf.domainname) > 0) + hostname += "." + string(buf.domainname); + return hostname; + } + + + string + datetime() + { + time_t t1 = time(NULL); + struct tm t2; + gmtime_r(&t1, &t2); + char buf[64 + 1]; + if (strftime(buf, sizeof(buf), "%F %T %Z", &t2) == 0) + return string("unknown"); + return string(buf); + } + + + StopWatch::StopWatch() + { + gettimeofday(&start_tv, NULL); + } + + + std::ostream& operator<<(std::ostream& s, const StopWatch& sw) + { + struct timeval stop_tv; + gettimeofday(&stop_tv, NULL); + + struct timeval tv; + timersub(&stop_tv, &sw.start_tv, &tv); + + return s << fixed << double(tv.tv_sec) + (double)(tv.tv_usec) / 1000000.0 << "s"; + } + + +const string app_ws = " \t\n"; + +} diff --git a/snapper/AppUtil.h b/snapper/AppUtil.h new file mode 100644 index 00000000..7cbaf19b --- /dev/null +++ b/snapper/AppUtil.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) [2004-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef APP_UTIL_H +#define APP_UTIL_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace snapper +{ + using std::string; + using std::list; + using std::map; + + +void createPath(const string& Path_Cv); +bool checkNormalFile(const string& Path_Cv); +bool checkDir(const string& Path_Cv); +bool getStatMode(const string& Path_Cv, mode_t& val ); +bool setStatMode(const string& Path_Cv, mode_t val ); + + list glob(const string& path, int flags); + +template +void classic(StreamType& stream) +{ + stream.imbue(std::locale::classic()); +} + + +enum LogLevel { DEBUG, MILESTONE, WARNING, ERROR }; + +void createLogger(const string& name, const string& logpath, const string& logfile); + +bool testLogLevel(LogLevel level); + +void prepareLogStream(std::ostringstream& stream); + +std::ostringstream* logStreamOpen(); + +void logStreamClose(LogLevel level, const char* file, unsigned line, + const char* func, std::ostringstream*); + +#define y2deb(op) y2log_op(snapper::DEBUG, __FILE__, __LINE__, __FUNCTION__, op) +#define y2mil(op) y2log_op(snapper::MILESTONE, __FILE__, __LINE__, __FUNCTION__, op) +#define y2war(op) y2log_op(snapper::WARNING, __FILE__, __LINE__, __FUNCTION__, op) +#define y2err(op) y2log_op(snapper::ERROR, __FILE__, __LINE__, __FUNCTION__, op) + +#define y2log_op(level, file, line, func, op) \ + do { \ + if (snapper::testLogLevel(level)) \ + { \ + std::ostringstream* __buf = snapper::logStreamOpen(); \ + *__buf << op; \ + snapper::logStreamClose(level, file, line, func, __buf); \ + } \ + } while (0) + + + string hostname(); + string datetime(); + + + class StopWatch + { + public: + + StopWatch(); + + friend std::ostream& operator<<(std::ostream& s, const StopWatch& sw); + + protected: + + struct timeval start_tv; + + }; + + + struct Text + { + Text() : native(), text() {} + Text(const string& native, const string& text) : native(native), text(text) {} + + void clear(); + + const Text& operator+=(const Text& a); + + string native; + string text; + }; + + + Text sformat(const Text& format, ...); + + + Text _(const char* msgid); + Text _(const char* msgid, const char* msgid_plural, unsigned long int n); + + +extern const string app_ws; + +} + +#endif diff --git a/snapper/Enum.cc b/snapper/Enum.cc new file mode 100644 index 00000000..0fdd454c --- /dev/null +++ b/snapper/Enum.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) [2010-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#include "snapper/Enum.h" +#include "snapper/SnapperTmpl.h" + + +namespace snapper +{ + + static const string snapshot_type_names[] = { + "single", "pre", "post" + }; + + const vector EnumInfo::names(snapshot_type_names, snapshot_type_names + + lengthof(snapshot_type_names)); + +} diff --git a/snapper/Enum.h b/snapper/Enum.h new file mode 100644 index 00000000..88ce6dfd --- /dev/null +++ b/snapper/Enum.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) [2010-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef ENUM_H +#define ENUM_H + + +#include +#include +#include +#include + +#include "snapper/Snapper.h" +#include "snapper/AppUtil.h" + + +namespace snapper +{ + using std::string; + using std::vector; + + + template struct EnumInfo {}; + + template <> struct EnumInfo { static const vector names; }; + + + template + const string& toString(EnumType value) + { + static_assert(std::is_enum::value, "not enum"); + + const vector& names = EnumInfo::names; + + // Comparisons must not be done with type of enum since the enum may + // define comparison operators. + assert((size_t)(value) < names.size()); + + return names[value]; + } + + + template + bool toValue(const string& str, EnumType& value, bool log_error = true) + { + static_assert(std::is_enum::value, "not enum"); + + const vector& names = EnumInfo::names; + + vector::const_iterator it = find(names.begin(), names.end(), str); + + if (it == names.end()) + { + if (log_error) + y2err("converting '" << str << "' to enum failed"); + return false; + } + + value = EnumType(it - names.begin()); + return true; + } + + + template + EnumType toValueWithFallback(const string& str, EnumType fallback, bool log_error = true) + { + EnumType value; + + if (toValue(str, value, log_error)) + return value; + + return fallback; + } + +} + + +#endif diff --git a/snapper/Makefile.am b/snapper/Makefile.am new file mode 100644 index 00000000..d1cbbbe2 --- /dev/null +++ b/snapper/Makefile.am @@ -0,0 +1,22 @@ +# +# Makefile.am for libsnapper/snapper +# + +lib_LTLIBRARIES = libsnapper.la + +libsnapper_la_SOURCES = \ + SnapperInterface.h \ + Snapper.cc Snapper.h \ + XmlFile.cc XmlFile.h \ + Enum.cc Enum.h \ + AppUtil.cc AppUtil.h \ + SnapperTmpl.h + +libsnapper_la_LDFLAGS = -version-info 2:0 +libsnapper_la_LIBADD = -lblocxx -lxml2 + +pkgincludedir = $(includedir)/snapper + +pkginclude_HEADERS = \ + SnapperInterface.h + diff --git a/snapper/Snapper.cc b/snapper/Snapper.cc new file mode 100644 index 00000000..8e2c95ca --- /dev/null +++ b/snapper/Snapper.cc @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2011 Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#include +#include +#include + +#include "snapper/Snapper.h" +#include "snapper/AppUtil.h" +#include "snapper/XmlFile.h" +#include "snapper/Enum.h" +#include "snapper/SnapperTmpl.h" + + +namespace snapper +{ + using namespace std; + + + bool initialized = false; + + map snapshots; + + + std::ostream& operator<<(std::ostream& s, const Snapshot& x) + { + s << "type:" << toString(x.type) << " date:" << x.date; + + if (!x.description.empty()) + s << " description:" << x.description; + + if (x.pre_num != 0) + s << " pre-num:" << x.pre_num; + + return s; + } + + + void + readSnapshots() + { + list infos = glob("/snapshots/*/snapshot.info", GLOB_NOSORT); + for (list::const_iterator it = infos.begin(); it != infos.end(); ++it) + { + unsigned int num; + it->substr(11) >> num; + + XmlFile file(*it); + const xmlNode* root = file.getRootElement(); + const xmlNode* node = getChildNode(root, "snapshot"); + + Snapshot snapshot; + + string tmp; + + if (getChildValue(node, "type", tmp)) + { + if (!toValue(tmp, snapshot.type, true)) + { + } + } + + getChildValue(node, "date", snapshot.date); + + getChildValue(node, "description", snapshot.description); + + getChildValue(node, "pre_num", snapshot.pre_num); + + snapshots[num] = snapshot; + } + } + + + void + initialize() + { + initialized = true; + + readSnapshots(); + } + + + void + assertInit() + { + if (!initialized) + initialize(); + } + + + const map& + getSnapshots() + { + assertInit(); + + return snapshots; + } + + + void + listSnapshots() + { + assertInit(); + + for (map::const_iterator it = snapshots.begin(); + it != snapshots.end(); ++it) + { + cout << it->first << " " << it->second << endl; + } + } + + + unsigned int + nextSnapshotNumber() + { + assertInit(); + + unsigned int num = 1; + + if (!snapshots.empty()) + num = snapshots.rbegin()->first + 1; + + return num; + } + + + bool + writeInfo(unsigned int num, const Snapshot& snapshot) + { + createPath("/snapshots/" + decString(num)); + + XmlFile xml; + xmlNode* node = xmlNewNode("snapshot"); + xml.setRootElement(node); + + setChildValue(node, "type", toString(snapshot.type)); + + setChildValue(node, "date", snapshot.date); + + if (snapshot.type == SINGLE || snapshot.type == PRE) + setChildValue(node, "description", snapshot.description); + + if (snapshot.type == POST) + setChildValue(node, "pre_num", snapshot.pre_num); + + xml.save("/snapshots/" + decString(num) + "/snapshot.info"); + + return true; + } + + + unsigned int + createSingleSnapshot(string description) + { + Snapshot snapshot; + snapshot.type = SINGLE; + snapshot.date = datetime(); + snapshot.description = description; + + unsigned int num = nextSnapshotNumber(); + snapshots[num] = snapshot; + writeInfo(num, snapshot); + return num; + } + + + unsigned int + createPreSnapshot(string description) + { + Snapshot snapshot; + snapshot.type = PRE; + snapshot.date = datetime(); + snapshot.description = description; + + unsigned int num = nextSnapshotNumber(); + snapshots[num] = snapshot; + writeInfo(num, snapshot); + return num; + } + + + unsigned int + createPostSnapshot(unsigned int pre_num) + { + Snapshot snapshot; + snapshot.type = POST; + snapshot.date = datetime(); + snapshot.pre_num = pre_num; + + unsigned int num = nextSnapshotNumber(); + snapshots[num] = snapshot; + writeInfo(num, snapshot); + return num; + } + +} diff --git a/snapper/Snapper.h b/snapper/Snapper.h new file mode 100644 index 00000000..2653bb37 --- /dev/null +++ b/snapper/Snapper.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011 Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef SNAPPER_H +#define SNAPPER_H + + +#include "snapper/SnapperInterface.h" + + +namespace snapper +{ + using namespace std; + + + extern bool initialized; + + extern map snapshots; + +}; + + +#endif diff --git a/snapper/SnapperInterface.h b/snapper/SnapperInterface.h new file mode 100644 index 00000000..a1bd5b08 --- /dev/null +++ b/snapper/SnapperInterface.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef SNAPPER_INTERFACE_H +#define SNAPPER_INTERFACE_H + + +#include +#include +#include + + +namespace snapper +{ + using std::string; + using std::map; + using std::list; + + + enum SnapshotType { SINGLE, PRE, POST }; + + + class Snapshot + { + public: + + Snapshot() : type(SINGLE), pre_num(0) {} + + SnapshotType type; + + string date; + + string description; // empty for type=POST + + unsigned int pre_num; // valid only for type=POST + + }; + + + const map& getSnapshots(); + + void listSnapshots(); // only for testing + + + unsigned int createSingleSnapshot(string description); + + unsigned int createPreSnapshot(string description); + + unsigned int createPostSnapshot(unsigned int pre_num); + +} + + +#endif diff --git a/snapper/SnapperTmpl.h b/snapper/SnapperTmpl.h new file mode 100644 index 00000000..baf9b9d6 --- /dev/null +++ b/snapper/SnapperTmpl.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) [2004-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef SNAPPER_TMPL_H +#define SNAPPER_TMPL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snapper/AppUtil.h" + +namespace snapper +{ + using namespace std; + + + template string decString(Num number) + { + static_assert(std::is_integral::value, "not integral"); + + std::ostringstream num_str; + classic(num_str); + num_str << number; + return num_str.str(); + } + + template string hexString(Num number) + { + static_assert(std::is_integral::value, "not integral"); + + std::ostringstream num_str; + classic(num_str); + num_str << std::hex << number; + return num_str.str(); + } + + template void operator>>(const string& d, Value& v) + { + std::istringstream Data(d); + classic(Data); + Data >> v; + } + + template std::ostream& operator<<( std::ostream& s, const std::list& l ) + { + s << "<"; + for( typename std::list::const_iterator i=l.begin(); i!=l.end(); i++ ) + { + if( i!=l.begin() ) + s << " "; + s << *i; + } + s << ">"; + return( s ); + } + + template std::ostream& operator<<( std::ostream& s, const std::deque& l ) + { + s << "<"; + for( typename std::deque::const_iterator i=l.begin(); i!=l.end(); i++ ) + { + if( i!=l.begin() ) + s << " "; + s << *i; + } + s << ">"; + return( s ); + } + + template std::ostream& operator<<( std::ostream& s, const std::pair& p ) + { + s << "[" << p.first << ":" << p.second << "]"; + return( s ); + } + + template std::ostream& operator<<( std::ostream& s, const std::map& m ) + { + s << "<"; + for( typename std::map::const_iterator i=m.begin(); i!=m.end(); i++ ) + { + if( i!=m.begin() ) + s << " "; + s << i->first << ":" << i->second; + } + s << ">"; + return( s ); + } + + + template + void logDiff(std::ostream& log, const char* text, const Type& lhs, const Type& rhs) + { + static_assert(!std::is_enum::value, "is enum"); + + if (lhs != rhs) + log << " " << text << ":" << lhs << "-->" << rhs; + } + + template + void logDiffHex(std::ostream& log, const char* text, const Type& lhs, const Type& rhs) + { + static_assert(std::is_integral::value, "not integral"); + + if (lhs != rhs) + log << " " << text << ":" << std::hex << lhs << "-->" << rhs << std::dec; + } + + template + void logDiffEnum(std::ostream& log, const char* text, const Type& lhs, const Type& rhs) + { + static_assert(std::is_enum::value, "not enum"); + + if (lhs != rhs) + log << " " << text << ":" << toString(lhs) << "-->" << toString(rhs); + } + + inline + void logDiff(std::ostream& log, const char* text, bool lhs, bool rhs) + { + if (lhs != rhs) + { + if (rhs) + log << " -->" << text; + else + log << " " << text << "-->"; + } + } + + + template + struct deref_less : public std::binary_function + { + bool operator()(const Type* x, const Type* y) const { return *x < *y; } + }; + + + template + struct deref_equal_to : public std::binary_function + { + bool operator()(const Type* x, const Type* y) const { return *x == *y; } + }; + + + template + void pointerIntoSortedList(list& l, Type* e) + { + l.insert(lower_bound(l.begin(), l.end(), e, deref_less()), e); + } + + + template + void clearPointerList(list& l) + { + for (typename list::iterator i = l.begin(); i != l.end(); ++i) + delete *i; + l.clear(); + } + + + template + bool contains(const ListType& l, const Type& value) + { + return find(l.begin(), l.end(), value) != l.end(); + } + + + template + bool contains_if(const ListType& l, Predicate pred) + { + return find_if(l.begin(), l.end(), pred) != l.end(); + } + + + template + typename Map::iterator mapInsertOrReplace(Map& m, const Key& k, const Value& v) + { + typename Map::iterator pos = m.lower_bound(k); + if (pos != m.end() && !typename Map::key_compare()(k, pos->first)) + pos->second = v; + else + pos = m.insert(pos, typename Map::value_type(k, v)); + return pos; + } + + template + typename List::const_iterator addIfNotThere(List& l, const Value& v) + { + typename List::const_iterator pos = find( l.begin(), l.end(), v ); + if (pos == l.end() ) + pos = l.insert(l.end(), v); + return pos; + } + + + template + inline unsigned int lengthof(T (&)[sz]) { return sz; } + +} + +#endif diff --git a/snapper/XmlFile.cc b/snapper/XmlFile.cc new file mode 100644 index 00000000..7470606a --- /dev/null +++ b/snapper/XmlFile.cc @@ -0,0 +1,148 @@ +/* + * Copyright (c) [2010-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#include + +#include "snapper/XmlFile.h" + + +namespace snapper +{ + + XmlFile::XmlFile() + : doc(xmlNewDoc((const xmlChar*) "1.0")) + { + } + + + XmlFile::XmlFile(const string& filename) + : doc(xmlReadFile(filename.c_str(), NULL, XML_PARSE_NOBLANKS | XML_PARSE_NONET)) + { + } + + + XmlFile::~XmlFile() + { + if (doc) + xmlFreeDoc(doc); + } + + + xmlNode* + xmlNewNode(const char* name) + { + return ::xmlNewNode(NULL, (const xmlChar*) name); + } + + + xmlNode* + xmlNewChild(xmlNode* node, const char* name) + { + return ::xmlNewChild(node, NULL, (const xmlChar*) name, NULL); + } + + + const xmlNode* + getChildNode(const xmlNode* node, const char* name) + { + for (const xmlNode* cur_node = node; cur_node; cur_node = cur_node->next) + { + if (strcmp(name, (const char*) cur_node->name) == 0) + { + if (cur_node->children) + return cur_node->children; + } + } + + return NULL; + } + + + list + getChildNodes(const xmlNode* node, const char* name) + { + list ret; + + for (const xmlNode* cur_node = node; cur_node; cur_node = cur_node->next) + { + if (cur_node->type == XML_ELEMENT_NODE && + strcmp(name, (const char*) cur_node->name) == 0) + { + if (cur_node->children) + ret.push_back(cur_node->children); + } + } + + return ret; + } + + + bool + getChildValue(const xmlNode* node, const char* name, string& value) + { + for (const xmlNode* cur_node = node; cur_node; cur_node = cur_node->next) + { + if (cur_node->type == XML_ELEMENT_NODE && + strcmp(name, (const char*) cur_node->name) == 0) + { + value = (const char*) cur_node->children->content; + return true; + } + } + + return false; + } + + + bool + getChildValue(const xmlNode* node, const char* name, bool& value) + { + string tmp; + if (!getChildValue(node, name, tmp)) + return false; + + value = tmp == "true"; + return true; + } + + + void + setChildValue(xmlNode* node, const char* name, const char* value) + { + xmlNewTextChild(node, NULL, (const xmlChar*) name, (const xmlChar*) value); + } + + + void + setChildValue(xmlNode* node, const char* name, const string& value) + { + xmlNewTextChild(node, NULL, (const xmlChar*) name, (const xmlChar*) value.c_str()); + } + + + void + setChildValue(xmlNode* node, const char* name, bool value) + { + xmlNewTextChild(node, NULL, (const xmlChar*) name, (const xmlChar*)(value ? "true" : "false")); + } + +} diff --git a/snapper/XmlFile.h b/snapper/XmlFile.h new file mode 100644 index 00000000..c148952d --- /dev/null +++ b/snapper/XmlFile.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) [2010-2011] Novell, Inc. + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * 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, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, you may + * find current contact information at www.novell.com. + */ + + +#ifndef XML_FILE_H +#define XML_FILE_H + + +#include +#include +#include +#include + +#include "snapper/AppUtil.h" + + +namespace snapper +{ + using namespace std; + + + class XmlFile : boost::noncopyable + { + + public: + + XmlFile(); + XmlFile(const string& filename); + + ~XmlFile(); + + bool save(const string& filename) + { return xmlSaveFormatFile(filename.c_str(), doc, 1); } + + void setRootElement(xmlNode* node) + { xmlDocSetRootElement(doc, node); } + + const xmlNode* getRootElement() const + { return xmlDocGetRootElement(doc); } + + private: + + xmlDoc* doc; + + }; + + + xmlNode* xmlNewNode(const char* name); + xmlNode* xmlNewChild(xmlNode* node, const char* name); + + + const xmlNode* getChildNode(const xmlNode* node, const char* name); + list getChildNodes(const xmlNode* node, const char* name); + + + bool getChildValue(const xmlNode* node, const char* name, string& value); + bool getChildValue(const xmlNode* node, const char* name, bool& value); + + template + bool getChildValue(const xmlNode* node, const char* name, Type& value) + { + string tmp; + if (!getChildValue(node, name, tmp)) + return false; + + std::istringstream istr(tmp); + classic(istr); + istr >> value; + return true; + } + + + void setChildValue(xmlNode* node, const char* name, const char* value); + void setChildValue(xmlNode* node, const char* name, const string& value); + void setChildValue(xmlNode* node, const char* name, bool value); + + template + void setChildValue(xmlNode* node, const char* name, const Type& value) + { + std::ostringstream ostr; + classic(ostr); + ostr << value; + setChildValue(node, name, ostr.str()); + } + + template + void setChildValue(xmlNode* node, const char* name, const list& values) + { + for (typename list::const_iterator it = values.begin(); it != values.end(); ++it) + setChildValue(node, name, *it); + } + +} + + +#endif