]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- first steps handling snapshot info files
authorArvin Schnell <aschnell@suse.de>
Mon, 10 Jan 2011 15:36:57 +0000 (16:36 +0100)
committerArvin Schnell <aschnell@suse.de>
Mon, 10 Jan 2011 15:36:57 +0000 (16:36 +0100)
28 files changed:
.gitignore
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.repo [new file with mode: 0644]
VERSION [new file with mode: 0644]
configure.in [new file with mode: 0644]
examples/.gitignore [new file with mode: 0644]
examples/Create.cc [new file with mode: 0644]
examples/List.cc [new file with mode: 0644]
examples/Makefile.am [new file with mode: 0644]
examples/Makefile.example [new file with mode: 0644]
package/.gitignore [new file with mode: 0644]
package/snapper.changes
package/snapper.spec [new file with mode: 0644]
snapper.spec.in [new file with mode: 0644]
snapper/.gitignore [new file with mode: 0644]
snapper/AppUtil.cc [new file with mode: 0644]
snapper/AppUtil.h [new file with mode: 0644]
snapper/Enum.cc [new file with mode: 0644]
snapper/Enum.h [new file with mode: 0644]
snapper/Makefile.am [new file with mode: 0644]
snapper/Snapper.cc [new file with mode: 0644]
snapper/Snapper.h [new file with mode: 0644]
snapper/SnapperInterface.h [new file with mode: 0644]
snapper/SnapperTmpl.h [new file with mode: 0644]
snapper/XmlFile.cc [new file with mode: 0644]
snapper/XmlFile.h [new file with mode: 0644]

index 89620f31052a2d00ffae6e76013d2e3bfc891452..e67cdafb7b0acd5f765f01d0289297621cf7c05f 100644 (file)
@@ -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 (file)
index 0000000..3be27c9
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Arvin Schnell <aschnell@suse.de>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d511905
--- /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.
+
+    <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.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..7ba4349
--- /dev/null
@@ -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 (file)
index 0000000..81d7c30
--- /dev/null
@@ -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 (file)
index 0000000..8acdd82
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.0.1
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..4899caa
--- /dev/null
@@ -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 (file)
index 0000000..648188c
--- /dev/null
@@ -0,0 +1,4 @@
+List.o
+List
+Create.o
+Create
diff --git a/examples/Create.cc b/examples/Create.cc
new file mode 100644 (file)
index 0000000..2c1e9f0
--- /dev/null
@@ -0,0 +1,22 @@
+
+#include <stdlib.h>
+#include <iostream>
+
+#include <snapper/Snapper.h>
+
+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 (file)
index 0000000..2f9758d
--- /dev/null
@@ -0,0 +1,16 @@
+
+#include <stdlib.h>
+#include <iostream>
+
+#include <snapper/Snapper.h>
+
+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 (file)
index 0000000..d8df744
--- /dev/null
@@ -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 (file)
index 0000000..945db75
--- /dev/null
@@ -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 (file)
index 0000000..c29f158
--- /dev/null
@@ -0,0 +1,2 @@
+snapper-*.tar.bz2
+snapper.spec
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..07ec0fa766d10701c4e926b354e08555b15f2baa 100644 (file)
@@ -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 (file)
index 0000000..cda500a
--- /dev/null
@@ -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 <aschnell@suse.de>
+
+%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 <aschnell@suse.de>
+
+%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 (file)
index 0000000..804799a
--- /dev/null
@@ -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 <aschnell@suse.de>
+
+%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 <aschnell@suse.de>
+
+%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 (file)
index 0000000..66a3f3f
--- /dev/null
@@ -0,0 +1,2 @@
+*.lo
+*.la
diff --git a/snapper/AppUtil.cc b/snapper/AppUtil.cc
new file mode 100644 (file)
index 0000000..fdccfef
--- /dev/null
@@ -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 <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <dirent.h>
+#include <string>
+#include <boost/algorithm/string.hpp>
+
+#include <blocxx/AppenderLogger.hpp>
+#include <blocxx/FileAppender.hpp>
+#include <blocxx/Logger.hpp>
+#include <blocxx/LogMessage.hpp>
+
+#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<string>
+    glob(const string& path, int flags)
+    {
+       list<string> 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 (file)
index 0000000..7cbaf19
--- /dev/null
@@ -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 <libintl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sstream>
+#include <locale>
+#include <string>
+#include <list>
+#include <map>
+
+
+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<string> glob(const string& path, int flags);
+
+template<class StreamType>
+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 (file)
index 0000000..0fdd454
--- /dev/null
@@ -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<string> EnumInfo<SnapshotType>::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 (file)
index 0000000..88ce6df
--- /dev/null
@@ -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 <assert.h>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include "snapper/Snapper.h"
+#include "snapper/AppUtil.h"
+
+
+namespace snapper
+{
+    using std::string;
+    using std::vector;
+
+
+    template <typename EnumType> struct EnumInfo {};
+
+    template <> struct EnumInfo<SnapshotType> { static const vector<string> names; };
+
+
+    template <typename EnumType>
+    const string& toString(EnumType value)
+    {
+       static_assert(std::is_enum<EnumType>::value, "not enum");
+
+       const vector<string>& names = EnumInfo<EnumType>::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 <typename EnumType>
+    bool toValue(const string& str, EnumType& value, bool log_error = true)
+    {
+       static_assert(std::is_enum<EnumType>::value, "not enum");
+
+       const vector<string>& names = EnumInfo<EnumType>::names;
+
+       vector<string>::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 <typename EnumType>
+    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 (file)
index 0000000..d1cbbbe
--- /dev/null
@@ -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 (file)
index 0000000..8e2c95c
--- /dev/null
@@ -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 <glob.h>
+#include <map>
+#include <iostream>
+
+#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<unsigned int, Snapshot> 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<string> infos = glob("/snapshots/*/snapshot.info", GLOB_NOSORT);
+       for (list<string>::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<unsigned int, Snapshot>&
+    getSnapshots()
+    {
+       assertInit();
+
+       return snapshots;
+    }
+
+
+    void
+    listSnapshots()
+    {
+       assertInit();
+
+       for (map<unsigned int, Snapshot>::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 (file)
index 0000000..2653bb3
--- /dev/null
@@ -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<unsigned int, Snapshot> snapshots;
+
+};
+
+
+#endif
diff --git a/snapper/SnapperInterface.h b/snapper/SnapperInterface.h
new file mode 100644 (file)
index 0000000..a1bd5b0
--- /dev/null
@@ -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 <string>
+#include <map>
+#include <list>
+
+
+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<unsigned int, Snapshot>& 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 (file)
index 0000000..baf9b9d
--- /dev/null
@@ -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 <functional>
+#include <ostream>
+#include <fstream>
+#include <sstream>
+#include <list>
+#include <map>
+#include <deque>
+#include <iostream>
+
+#include "snapper/AppUtil.h"
+
+namespace snapper
+{
+    using namespace std;
+
+
+    template<class Num> string decString(Num number)
+    {
+       static_assert(std::is_integral<Num>::value, "not integral");
+
+       std::ostringstream num_str;
+       classic(num_str);
+       num_str << number;
+       return num_str.str();
+    }
+
+    template<class Num> string hexString(Num number)
+    {
+       static_assert(std::is_integral<Num>::value, "not integral");
+
+       std::ostringstream num_str;
+       classic(num_str);
+       num_str << std::hex << number;
+       return num_str.str();
+    }
+
+    template<class Value> void operator>>(const string& d, Value& v)
+    {
+       std::istringstream Data(d);
+       classic(Data);
+       Data >> v;
+    }
+
+    template<class Value> std::ostream& operator<<( std::ostream& s, const std::list<Value>& l )
+    {
+       s << "<";
+       for( typename std::list<Value>::const_iterator i=l.begin(); i!=l.end(); i++ )
+       {
+           if( i!=l.begin() )
+               s << " ";
+           s << *i;
+       }
+       s << ">";
+       return( s );
+    }
+
+    template<class Value> std::ostream& operator<<( std::ostream& s, const std::deque<Value>& l )
+    {
+       s << "<";
+       for( typename std::deque<Value>::const_iterator i=l.begin(); i!=l.end(); i++ )
+       {
+           if( i!=l.begin() )
+               s << " ";
+           s << *i;
+       }
+       s << ">";
+       return( s );
+    }
+
+    template<class F, class S> std::ostream& operator<<( std::ostream& s, const std::pair<F,S>& p )
+    {
+       s << "[" << p.first << ":" << p.second << "]";
+       return( s );
+    }
+
+    template<class Key, class Value> std::ostream& operator<<( std::ostream& s, const std::map<Key,Value>& m )
+    {
+       s << "<";
+       for( typename std::map<Key,Value>::const_iterator i=m.begin(); i!=m.end(); i++ )
+       {
+           if( i!=m.begin() )
+               s << " ";
+           s << i->first << ":" << i->second;
+       }
+       s << ">";
+       return( s );
+    }
+
+
+    template <typename Type>
+    void logDiff(std::ostream& log, const char* text, const Type& lhs, const Type& rhs)
+    {
+       static_assert(!std::is_enum<Type>::value, "is enum");
+
+       if (lhs != rhs)
+           log << " " << text << ":" << lhs << "-->" << rhs;
+    }
+
+    template <typename Type>
+    void logDiffHex(std::ostream& log, const char* text, const Type& lhs, const Type& rhs)
+    {
+       static_assert(std::is_integral<Type>::value, "not integral");
+
+       if (lhs != rhs)
+           log << " " << text << ":" << std::hex << lhs << "-->" << rhs << std::dec;
+    }
+
+    template <typename Type>
+    void logDiffEnum(std::ostream& log, const char* text, const Type& lhs, const Type& rhs)
+    {
+       static_assert(std::is_enum<Type>::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<class Type>
+    struct deref_less : public std::binary_function<const Type*, const Type*, bool>
+    {
+       bool operator()(const Type* x, const Type* y) const { return *x < *y; }
+    };
+
+
+    template<class Type>
+    struct deref_equal_to : public std::binary_function<const Type*, const Type*, bool>
+    {
+       bool operator()(const Type* x, const Type* y) const { return *x == *y; }
+    };
+
+
+    template <class Type>
+    void pointerIntoSortedList(list<Type*>& l, Type* e)
+    {
+       l.insert(lower_bound(l.begin(), l.end(), e, deref_less<Type>()), e);
+    }
+
+
+    template <class Type>
+    void clearPointerList(list<Type*>& l)
+    {
+       for (typename list<Type*>::iterator i = l.begin(); i != l.end(); ++i)
+           delete *i;
+       l.clear();
+    }
+
+
+    template <typename ListType, typename Type>
+    bool contains(const ListType& l, const Type& value)
+    {
+       return find(l.begin(), l.end(), value) != l.end();
+    }
+
+
+    template <typename ListType, typename Predicate>
+    bool contains_if(const ListType& l, Predicate pred)
+    {
+       return find_if(l.begin(), l.end(), pred) != l.end();
+    }
+
+
+    template<typename Map, typename Key, typename Value>
+    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, typename Value>
+    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 <class T, unsigned int sz>
+    inline unsigned int lengthof(T (&)[sz]) { return sz; }
+
+}
+
+#endif
diff --git a/snapper/XmlFile.cc b/snapper/XmlFile.cc
new file mode 100644 (file)
index 0000000..7470606
--- /dev/null
@@ -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 <string.h>
+
+#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<const xmlNode*>
+    getChildNodes(const xmlNode* node, const char* name)
+    {
+       list<const xmlNode*> 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 (file)
index 0000000..c148952
--- /dev/null
@@ -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 <libxml/tree.h>
+#include <string>
+#include <list>
+#include <boost/noncopyable.hpp>
+
+#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<const xmlNode*> 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<typename Type>
+    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<typename Type>
+    void setChildValue(xmlNode* node, const char* name, const Type& value)
+    {
+       std::ostringstream ostr;
+       classic(ostr);
+       ostr << value;
+       setChildValue(node, name, ostr.str());
+    }
+
+    template<typename Type>
+    void setChildValue(xmlNode* node, const char* name, const list<Type>& values)
+    {
+       for (typename list<Type>::const_iterator it = values.begin(); it != values.end(); ++it)
+           setChildValue(node, name, *it);
+    }
+
+}
+
+
+#endif