From dc28f5d5e47fda26d794d6c20860e4f2418dcff3 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 1 Jan 2012 17:07:50 +0100 Subject: [PATCH] First cut selection list --- bacula/src/lib/Makefile.in | 6 +- bacula/src/lib/lib.h | 4 +- bacula/src/lib/sellist.c | 199 +++++++++++++++++++++++++++++++++++++ bacula/src/lib/sellist.h | 111 +++++++++++++++++++++ 4 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 bacula/src/lib/sellist.c create mode 100644 bacula/src/lib/sellist.h diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 312e328ddb..88f416abed 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -39,7 +39,7 @@ INCLUDE_FILES = ../baconfig.h ../bacula.h ../bc_types.h \ fnmatch.h guid_to_name.h htable.h lex.h \ lib.h md5.h mem_pool.h message.h mntent_cache.h \ openssl.h plugins.h protos.h queue.h rblist.h \ - runscript.h rwlock.h serial.h sha1.h \ + runscript.h rwlock.h serial.h sellist.h sha1.h \ smartall.h status.h tls.h tree.h var.h \ waitq.h watchdog.h workq.h \ parse_conf.h \ @@ -55,7 +55,7 @@ LIBBAC_SRCS = attr.c base64.c berrno.c bsys.c binflate.c bget_msg.c \ guid_to_name.c hmac.c jcr.c lex.c alist.c dlist.c \ md5.c message.c mem_pool.c mntent_cache.c openssl.c \ plugins.c priv.c queue.c bregex.c \ - rwlock.c scan.c serial.c sha1.c \ + rwlock.c scan.c sellist.c serial.c sha1.c \ signal.c smartall.c rblist.c tls.c tree.c \ util.c var.c watchdog.c workq.c btimers.c \ address_conf.c breg.c htable.c lockmgr.c devlock.c @@ -167,7 +167,7 @@ devlock_test: Makefile htable_test: Makefile rm -f htable.o - $(CXX) -DTEST_SMALL_HTABLE -DTEST_NON_CHAR -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) htable.c + $(CXX) -DTEST_SMALL_HTABLE -DTEST_NON_CHAR -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) htable.c $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ htable.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS) rm -f htable.o $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) htable.c diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index b2339a8945..b81f89f747 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + Copyright (C) 2000-2011 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -32,7 +32,6 @@ * that we use within Bacula. bacula.h includes this * file and thus picks up everything we need in lib. * - * Version $Id$ */ #include "smartall.h" @@ -70,4 +69,5 @@ #include "var.h" #include "guid_to_name.h" #include "htable.h" +#include "sellist.h" #include "protos.h" diff --git a/bacula/src/lib/sellist.c b/bacula/src/lib/sellist.c new file mode 100644 index 0000000000..eeb37ce2b2 --- /dev/null +++ b/bacula/src/lib/sellist.c @@ -0,0 +1,199 @@ +/* + Bacula(R) - The Network Backup Solution + + Copyright (C) 2011-2011 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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 Affero 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. + + Bacula(R) is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Kern Sibbald, January MMXII + * + * Selection list. A string of integers separated by commas + * representing items selected. Ranges of the form nn-mm + * are also permitted. + */ + +#include "bacula.h" +#include "sellist.h" + +/* + * Returns next item + * error if returns -1 and errmsg set + * end of items if returns -1 and errmsg NULL + */ +int64_t sellist::next() +{ + if (e == NULL) { + goto bail_out; + } + errmsg = NULL; + if (beg <= end) { + return beg++; + } + /* + * As we walk the list, we set EOF in + * the end of the next item to ease scanning, + * but save and then restore the character. + */ + for (p=e; p && *p; p=e) { + /* Check for list */ + e = strchr(p, ','); + if (e) { + esave = *e; + *e++ = 0; + } else { + esave = 0; + } + /* Check for range */ + h = strchr(p, '-'); /* range? */ + if (h == p) { + errmsg = _("Negative numbers not permitted.\n"); + goto bail_out; + } + if (h) { + hsave = *h; + *h++ = 0; + if (!is_an_integer(h)) { + errmsg = _("Range end is not integer.\n"); + goto bail_out; + } + skip_spaces(&p); + if (!is_an_integer(p)) { + errmsg = _("Range start is not an integer.\n"); + goto bail_out; + } + beg = str_to_int64(p); + end = str_to_int64(h); + if (end < beg) { + errmsg = _("Range end not bigger than start.\n"); + goto bail_out; + } + } else { + hsave = 0; + skip_spaces(&p); + if (!is_an_integer(p)) { + errmsg = _("Input value is not an integer.\n"); + goto bail_out; + } + beg = end = str_to_int64(p); + } + if (esave) { + *(e-1) = esave; + } + if (hsave) { + *(h-1) = hsave; + } + if (beg <= 0 || end <= 0) { + errmsg = _("Selection items must be be greater than zero.\n"); + goto bail_out; + } + if (end > max) { + errmsg = _("Selection item too large.\n"); + goto bail_out; + } + if (beg <= end) { + return beg++; + } + } + /* End of items */ + errmsg = NULL; /* No error */ + return -1; + +bail_out: + return -1; /* Error, errmsg set */ +} + + +/* + * Set selection string and optionally scan it + * returns false on error in string + * returns true if OK + */ +bool sellist::set_string(char *string, bool scan=true) +{ + /* + * Copy string, because we write into it, + * then scan through it once to find any + * errors. + */ + if (str) { + free(str); + } + e = str = bstrdup(string); + end = 0; + beg = 1; + num_items = 0; + if (scan) { + while (next() >= 0) { + num_items++; + } + if (get_errmsg()) { + return false; + } + e = str; + end = 0; + beg = 1; + } + return true; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv, char **env) +{ + char *msg; + sellist sl; + int i; + + if (!argv[1]) { + msg = _("No input string given.\n"); + goto bail_out; + } + Dmsg1(000, "argv[1]=%s\n", argv[1]); + + strip_trailing_junk(argv[1]); + sl.set_string(argv[1]); + if ((msg = sl.get_errmsg())) { + goto bail_out; + } + while ((i=sl.next()) >= 0) { + Dmsg1(000, "%d\n", i); + } + if ((msg = sl.get_errmsg())) { + goto bail_out; + } + printf("\nPass 2\n"); + sl.set_string(argv[1]); + while ((i=sl.next()) >= 0) { + Dmsg1(000, "%d\n", i); + } + if ((msg = sl.get_errmsg())) { + goto bail_out; + } + return 0; + +bail_out: + Dmsg1(000, "Error: %s\n", msg); + return 1; + +} +#endif /* TEST_PROGRAM */ diff --git a/bacula/src/lib/sellist.h b/bacula/src/lib/sellist.h new file mode 100644 index 0000000000..99365bdda8 --- /dev/null +++ b/bacula/src/lib/sellist.h @@ -0,0 +1,111 @@ +/* + Bacula(R) - The Network Backup Solution + + Copyright (C) 2011-2011 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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 Affero 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. + + Bacula(R) is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Kern Sibbald, January MMXII + * + * Selection list. A string of integers separated by commas + * representing items selected. Ranges of the form nn-mm + * are also permitted. + */ + +/* + * Loop var through each member of list + */ +#define foreach_sellist(var, list) \ + for((var)=(list)->first(); (var)>=0; (var)=(list)->next() ) + + +class sellist : public SMARTALLOC { + char *errmsg; + char *p, *e, *h; + char esave, hsave; + int64_t beg, end; + int64_t max; + int num_items; + char *str; +public: + sellist(); + ~sellist(); + bool set_string(char *string, bool scan); + int64_t first(); + int64_t next(); + int size() const; + char *get_errmsg(); +}; + +/* + * Initialize the list structure + */ +inline sellist::sellist() +{ + num_items = 0; + max = 99999; + str = NULL; + e = errmsg = NULL; +} + +/* + * Destroy the list + */ +inline sellist::~sellist() +{ + if (str) { + free(str); + str = NULL; + } +} + +/* + * Return list size, but only if scan enabled on string + */ +inline int sellist::size() const +{ + return num_items; +} + +/* + * Return error message or NULL if none + */ +inline char *sellist::get_errmsg() +{ + return errmsg; +} + +/* + * Returns first item + * error if returns -1 and errmsg set + * end of items if returns -1 and errmsg NULL + */ +inline int64_t sellist::first() +{ + e = str; + end = 0; + beg = 1; + errmsg = NULL; + return next(); +} -- 2.39.5