]> git.tuebingen.mpg.de Git - dss.git/commitdiff
Merge branch 'refs/heads/t/kill-w'
authorAndre Noll <maan@tuebingen.mpg.de>
Sat, 18 Nov 2017 14:54:03 +0000 (15:54 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 18 Nov 2017 14:56:55 +0000 (15:56 +0100)
Two patches which make life easier for shutdown scripts which need
to terminate the dss process, but would like to wait until the exit
hook completed.

The merge conflicted in dss.suite, but this was trivial to fix.

Cooking for a week.

* refs/heads/t/kill-w:
  kill: New option --wait.
  run: Wait for children to die.

15 files changed:
.gitignore
INSTALL
Makefile
NEWS
README
df.c
dss.c
dss.dia [deleted file]
dss.suite
err.h
file.h
gcc-compat.h
mklogo [new file with mode: 0755]
snap.h
tv.c

index 977f1dc03ba9e4c5c1e6f557d99abfc48df34999..1bb2a256e58d29073cf553ece92b355f5bf2ef7b 100644 (file)
@@ -1,7 +1,9 @@
 Makefile.deps
-*.[oa]
-cmdline.[ch]
+*.o
+*.swp
 dss.lsg.*
 dss
 dss.1
 dss.1.html
+dss.png
+index.html
diff --git a/INSTALL b/INSTALL
index 8c70c34a20e57cb6e87ab47e97391ff297ed1609..09d8505b3a46d5381a8626fd462ee7a6fd149af5 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -24,7 +24,7 @@ to install in /usr/local, or
 
 to install in /somewhere/else.
 
-Also make sure that [rsync](http://rsync.samba.org/) is installed on
+Also make sure that [rsync](https://rsync.samba.org/) is installed on
 your system. Version 2.6.1 or newer is required.
 
 Examples:
@@ -70,7 +70,7 @@ system boundaries and increases the number of snapshots.
                rsync-option "--exclude-from=/etc/dss.exclude"
                # don't cross filesystem boundaries
                rsync-option "--one-file-system"
-               # maintain 2^6 - 1 = 63 snaphots
+               # maintain 2^6 - 1 = 63 snapshots
                num-intervals "6"
 
 The /etc/dss.exclude file could look like this (see rsync(1) for
index a8e045c2e755673d1aa28062684c2096db4ef818..f5c34af7b590145c99d3a8ced9b2badfd7179048 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -37,8 +37,8 @@ dss: $(dss_objects)
 %.o: %.c Makefile
        $(CC) -c $(DSS_CPPFLAGS) $(CPPFLAGS) $(DSS_CFLAGS) $(CFLAGS) $<
 
-%.png: %.dia
-       dia -e $@ -t png $<
+dss.png: mklogo
+       ./mklogo > $@
 
 %.lsg.h: %.suite
        lopsubgen --gen-h=$@ < $<
diff --git a/NEWS b/NEWS
index 755cad21834cc7b6d150746e6555544d706802c6..0f9b6d27b860cef44cd4b3c68de75154a2c58da7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,26 +1,49 @@
 -----------------------
-x.y.z (to be announced)
+1.0.0 (to be announced)
 -----------------------
 
- - Improved error diagnostics for the kill subcommand.
+ - The gengetopt option parser has been replaced by the
+ [lopsub](http://people.tuebingen.mpg.de/maan/lopsub) library. Hence
+ lopsub must be installed to compile this package. help2man is
+ no longer required since lopsub has built-in roff support.
+
+ - New subcommand "configtest" to check the command line options and
+ the configuration file for syntactic correctness.
+
+ - New option: --mountpoint. If this option is given, dss aborts if
+ no file system is mounted on the destination directory.
+
+ - New option --checksum to let rsync compute checksums occasionally.
+
+ - The kill subcommand gained the new --wait option which instructs dss
+ to wait until the signalled process has terminated.
 
  - The --no-resume option has been removed.
 
- - The gengetopt option parser has been replaced by the
- [lopsub](http://people.tuebingen.mpg.de/~maan/lopsub) library. Hence
- lopsub must be installed to compile this package. Also help2man is
- no longer required since lopsub has built-in roff support.
+ - On exit, the run subcommand now waits for any previously spawned
+ rsync or rm processes to terminate.
 
- - "make install" will install the executable and the man page.
+ - The ls subcommand now shows the age of incomplete snapshots rather
+ than 0:00.
 
  - In run mode, dss no longer exits successfully if another instance
  is already running.
 
- - New option --checksum to let rsync compute checksums occasionally.
+ - The command specified as the argument to --exit-hook is now subject
+ to word splitting. Previously, the string was executed as-is.
+
+ - Improved error diagnostics for the kill subcommand.
+
+ - For all subcommands other than "run", timestamps and function names
+ are omitted from the log output.
+
+ - "make install" will install the executable and the man page.
 
  - CFLAGS, CPPFLAGS and LDFLAGS can now be used to override the flags
  of the build system.
 
+ - The dss logo is now created with ImageMagick rather than dia.
+
 ------------------
 0.1.7 (2017-04-17)
 ------------------
diff --git a/README b/README
index c5abb2923cc7ca9cd415ccdcbce9dd56ece4d0fd..79b88898348ead8869b62590d548e848072a20fe 100644 (file)
--- a/README
+++ b/README
@@ -11,7 +11,7 @@ configured, and there is no database to maintain.
 
 dss is also user-friendly because users can browse the snapshot
 directories without admin intervention and see the contents of the file
-system at the various times a snapshot was taken. Each snaphot looks
+system at the various times a snapshot was taken. Each snapshot looks
 like a full backup, so users can easily restore accidentally removed
 files by using their favorite file browser to simply copy files from
 the snapshot directory back to the live system.
diff --git a/df.c b/df.c
index 003becccddebe5231289afb63c5c527c550357b1..82d14ba9863a5975fd0b9ef46313ec5fd720becf 100644 (file)
--- a/df.c
+++ b/df.c
@@ -18,7 +18,7 @@
 
 int get_disk_space(const char *path, struct disk_space *result)
 {
-       /* using floats allows to not care about integer overflows */
+       /* With floats we don't need to care about integer overflows. */
        float total_blocks, available_blocks, blocksize;
        float total_inodes, available_inodes;
 
diff --git a/dss.c b/dss.c
index 60c05916424e5336401abb6ee284049fdfb5dc04..491b8aa791fdafc29589ec08eae878e9e67039be 100644 (file)
--- a/dss.c
+++ b/dss.c
@@ -63,6 +63,8 @@ static struct lls_parse_result *cmdline_lpr, *lpr;
 
 /** Parsed subcommand options. */
 static struct lls_parse_result *cmdline_sublpr, *sublpr;
+/* The executing subcommand (NULL at startup). */
+static const struct lls_command *subcmd;
 /** Wether daemon_init() was called. */
 static bool daemonized;
 /** Non-NULL if we log to a file. */
@@ -242,16 +244,19 @@ __printf_1_2 void dss_log(const char* fmt,...)
        if (loglevel < lpr_ll)
                return;
        outfd = logfile? logfile : stderr;
-       time(&t1);
-       tm = localtime(&t1);
-       strftime(str, sizeof(str), "%b %d %H:%M:%S", tm);
-       fprintf(outfd, "%s ", str);
-       if (lpr_ll <= INFO)
-               fprintf(outfd, "%i: ", loglevel);
+       if (subcmd == CMD_PTR(RUN)) {
+               time(&t1);
+               tm = localtime(&t1);
+               strftime(str, sizeof(str), "%b %d %H:%M:%S", tm);
+               fprintf(outfd, "%s ", str);
+               if (lpr_ll <= INFO)
+                       fprintf(outfd, "%i: ", loglevel);
+       }
+       if (subcmd == CMD_PTR(RUN))
 #ifdef DSS_NO_FUNC_NAMES
-       fprintf(outfd, "%s:%d: ", location_file, location_line);
+               fprintf(outfd, "%s:%d: ", location_file, location_line);
 #else
-       fprintf(outfd, "%s: ", location_func);
+               fprintf(outfd, "%s: ", location_func);
 #endif
        va_start(argp, fmt);
        vfprintf(outfd, fmt, argp);
@@ -297,6 +302,7 @@ static int send_signal(int sig, bool wait)
                dss_msg("%d\n", (int)pid);
                return 0;
        }
+       DSS_NOTICE_LOG(("sending signal %d to pid %d\n", sig, (int)pid));
        ret = kill(pid, sig);
        if (ret < 0)
                return -ERRNO_TO_DSS_ERROR(errno);
@@ -534,7 +540,7 @@ static struct snapshot *find_orphaned_snapshot(struct snapshot_list *sl)
        struct snapshot *s;
        int i;
 
-       DSS_DEBUG_LOG(("looking for orphaned snapshots\n"));
+       DSS_DEBUG_LOG(("looking for old incomplete snapshots\n"));
        FOR_EACH_SNAPSHOT(s, i, sl) {
                if (snapshot_is_being_created(s))
                        continue;
@@ -748,6 +754,7 @@ static int try_to_free_disk_space(void)
        if (!low_disk_space)
                goto out;
        DSS_WARNING_LOG(("disk space low and nothing obvious to remove\n"));
+       why = "oldest";
        victim = find_oldest_removable_snapshot(&sl);
        if (victim)
                goto remove;
@@ -1072,20 +1079,39 @@ static int handle_sigchld(void)
        return -E_BUG;
 }
 
+/* also checks if . is a mountpoint, if --mountpoint was given */
 static int change_to_dest_dir(void)
 {
        int ret;
        const char *dd = OPT_STRING_VAL(DSS, DEST_DIR);
+       struct stat dot, dotdot;
 
        DSS_INFO_LOG(("changing cwd to %s\n", dd));
-       if (chdir(dd) >= 0)
-               return 1;
-       ret = -ERRNO_TO_DSS_ERROR(errno);
-       DSS_ERROR_LOG(("could not change cwd to %s\n", dd));
-       return ret;
+       if (chdir(dd) < 0) {
+               ret = -ERRNO_TO_DSS_ERROR(errno);
+               DSS_ERROR_LOG(("could not change cwd to %s\n", dd));
+               return ret;
+       }
+       if (!OPT_GIVEN(DSS, MOUNTPOINT))
+               return 0;
+       if (stat(".", &dot) < 0) {
+               ret = -ERRNO_TO_DSS_ERROR(errno);
+               DSS_ERROR_LOG(("could not stat .\n"));
+               return ret;
+       }
+       if (stat("..", &dotdot) < 0) {
+               ret = -ERRNO_TO_DSS_ERROR(errno);
+               DSS_ERROR_LOG(("could not stat ..\n"));
+               return ret;
+       }
+       if (dot.st_dev == dotdot.st_dev && dot.st_ino != dotdot.st_ino) {
+               DSS_ERROR_LOG(("mountpoint check failed for %s\n", dd));
+               return -E_MOUNTPOINT;
+       }
+       return 1;
 }
 
-static int check_config(const struct lls_command *cmd)
+static int check_config(void)
 {
        int ret;
        uint32_t unit_interval = OPT_UINT32_VAL(DSS, UNIT_INTERVAL);
@@ -1101,13 +1127,13 @@ static int check_config(const struct lls_command *cmd)
                DSS_ERROR_LOG(("bad number of intervals: %i\n", num_intervals));
                return -E_INVALID_NUMBER;
        }
-       if (cmd == CMD_PTR(RUN) || cmd == CMD_PTR(CREATE))
+       if (subcmd == CMD_PTR(RUN) || subcmd == CMD_PTR(CREATE))
                if (!OPT_GIVEN(DSS, SOURCE_DIR)) {
                        DSS_ERROR_LOG(("--source-dir required\n"));
                        return -E_SYNTAX;
                }
-       if (cmd == CMD_PTR(RUN) || cmd == CMD_PTR(CREATE)
-                       || cmd == CMD_PTR(LS) || cmd == CMD_PTR(PRUNE)) {
+       if (subcmd == CMD_PTR(RUN) || subcmd == CMD_PTR(CREATE)
+                       || subcmd == CMD_PTR(LS) || subcmd == CMD_PTR(PRUNE)) {
                if (!OPT_GIVEN(DSS, DEST_DIR)) {
                        DSS_ERROR_LOG(("--dest-dir required\n"));
                        return -E_SYNTAX;
@@ -1245,7 +1271,7 @@ static int handle_sighup(void)
        ret = parse_config_file(true /* SIGHUP */, CMD_PTR(RUN));
        if (ret < 0)
                return ret;
-       ret = check_config(CMD_PTR(RUN));
+       ret = check_config();
        if (ret < 0)
                return ret;
        close_log(logfile);
@@ -1519,15 +1545,18 @@ out:
 
 static void exit_hook(int exit_code)
 {
-       const char *argv[3];
        pid_t pid;
-
-       argv[0] = OPT_STRING_VAL(DSS, EXIT_HOOK);
-       argv[1] = dss_strerror(-exit_code);
-       argv[2] = NULL;
-
-       DSS_NOTICE_LOG(("executing %s %s\n", argv[0], argv[1]));
-       dss_exec(&pid, argv[0], (char **)argv);
+       char **argv, *tmp = dss_strdup(OPT_STRING_VAL(DSS, EXIT_HOOK));
+       unsigned n = split_args(tmp, &argv, " \t");
+
+       n++;
+       argv = dss_realloc(argv, (n + 1) * sizeof(char *));
+       argv[n - 1] = dss_strdup(dss_strerror(-exit_code));
+       argv[n] = NULL;
+       dss_exec(&pid, argv[0], argv);
+       free(argv[n - 1]);
+       free(argv);
+       free(tmp);
 }
 
 static void lock_dss_or_die(void)
@@ -1704,19 +1733,30 @@ static int com_ls(void)
        int i;
        struct snapshot_list sl;
        struct snapshot *s;
+       int64_t now = get_current_time();
 
        dss_get_snapshot_list(&sl);
        FOR_EACH_SNAPSHOT(s, i, &sl) {
-               int64_t d = 0;
+               int64_t d;
                if (s->flags & SS_COMPLETE)
                        d = (s->completion_time - s->creation_time) / 60;
-               dss_msg("%u\t%s\t%3" PRId64 ":%02" PRId64 "\n", s->interval, s->name, d/60, d%60);
+               else
+                       d = (now - s->creation_time) / 60;
+               dss_msg("%u\t%s\t%3" PRId64 ":%02" PRId64 "\n", s->interval,
+                       s->name, d / 60, d % 60);
        }
        free_snapshot_list(&sl);
        return 1;
 }
 EXPORT_CMD_HANDLER(ls);
 
+static int com_configtest(void)
+{
+       printf("Syntax Ok\n");
+       return 0;
+}
+EXPORT_CMD_HANDLER(configtest);
+
 static int setup_signal_handling(void)
 {
        int ret;
@@ -1758,7 +1798,7 @@ static void show_subcommand_summary(void)
        for (i = 1; (cmd = lls_cmd(i, dss_suite)); i++) {
                const char *name = lls_command_name(cmd);
                const char *purpose = lls_purpose(cmd);
-               printf("%-10s%s\n", name, purpose);
+               printf("%-11s%s\n", name, purpose);
        }
        exit(EXIT_SUCCESS);
 }
@@ -1766,18 +1806,17 @@ static void show_subcommand_summary(void)
 int main(int argc, char **argv)
 {
        int ret;
-       const struct lls_command *cmd = CMD_PTR(DSS);
        char *errctx = NULL;
        unsigned num_inputs;
-       const struct dss_user_data *ud = NULL;
+       const struct dss_user_data *ud;
 
-       ret = lls_parse(argc, argv, cmd, &cmdline_lpr, &errctx);
+       ret = lls_parse(argc, argv, CMD_PTR(DSS), &cmdline_lpr, &errctx);
        if (ret < 0) {
                ret = lopsub_error(ret, &errctx);
                goto out;
        }
        lpr = cmdline_lpr;
-       ret = parse_config_file(false /* no SIGHUP */, cmd);
+       ret = parse_config_file(false /* no SIGHUP */, CMD_PTR(DSS));
        if (ret < 0)
                goto out;
        handle_version_and_help();
@@ -1789,24 +1828,24 @@ int main(int argc, char **argv)
                ret = lopsub_error(ret, &errctx);
                goto out;
        }
-       cmd = lls_cmd(ret, dss_suite);
-       ret = lls_parse(num_inputs, argv + argc - num_inputs, cmd,
+       subcmd = lls_cmd(ret, dss_suite);
+       ret = lls_parse(num_inputs, argv + argc - num_inputs, subcmd,
                &cmdline_sublpr, &errctx);
        if (ret < 0) {
                ret = lopsub_error(ret, &errctx);
                goto out;
        }
        sublpr = cmdline_sublpr;
-       ret = parse_config_file(false /* no SIGHUP */, cmd);
+       ret = parse_config_file(false /* no SIGHUP */, subcmd);
        if (ret < 0)
                goto out;
-       ret = check_config(cmd);
+       ret = check_config();
        if (ret < 0)
                goto out;
        ret = setup_signal_handling();
        if (ret < 0)
                goto out;
-       ud = lls_user_data(cmd);
+       ud = lls_user_data(subcmd);
        ret = ud->handler();
        signal_shutdown();
 out:
@@ -1819,8 +1858,8 @@ out:
        lls_free_parse_result(lpr, CMD_PTR(DSS));
        if (lpr != cmdline_lpr)
                lls_free_parse_result(cmdline_lpr, CMD_PTR(DSS));
-       lls_free_parse_result(sublpr, cmd);
+       lls_free_parse_result(sublpr, subcmd);
        if (sublpr != cmdline_sublpr)
-               lls_free_parse_result(cmdline_sublpr, cmd);
+               lls_free_parse_result(cmdline_sublpr, subcmd);
        exit(ret >= 0? EXIT_SUCCESS : EXIT_FAILURE);
 }
diff --git a/dss.dia b/dss.dia
deleted file mode 100644 (file)
index a02f700..0000000
--- a/dss.dia
+++ /dev/null
@@ -1,960 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
-  <dia:diagramdata>
-    <dia:attribute name="background">
-      <dia:color val="#ffffff"/>
-    </dia:attribute>
-    <dia:attribute name="pagebreak">
-      <dia:color val="#000099"/>
-    </dia:attribute>
-    <dia:attribute name="paper">
-      <dia:composite type="paper">
-        <dia:attribute name="name">
-          <dia:string>#A4#</dia:string>
-        </dia:attribute>
-        <dia:attribute name="tmargin">
-          <dia:real val="2.8222000598907471"/>
-        </dia:attribute>
-        <dia:attribute name="bmargin">
-          <dia:real val="2.8222000598907471"/>
-        </dia:attribute>
-        <dia:attribute name="lmargin">
-          <dia:real val="2.8222000598907471"/>
-        </dia:attribute>
-        <dia:attribute name="rmargin">
-          <dia:real val="2.8222000598907471"/>
-        </dia:attribute>
-        <dia:attribute name="is_portrait">
-          <dia:boolean val="true"/>
-        </dia:attribute>
-        <dia:attribute name="scaling">
-          <dia:real val="1"/>
-        </dia:attribute>
-        <dia:attribute name="fitto">
-          <dia:boolean val="false"/>
-        </dia:attribute>
-      </dia:composite>
-    </dia:attribute>
-    <dia:attribute name="grid">
-      <dia:composite type="grid">
-        <dia:attribute name="width_x">
-          <dia:real val="1"/>
-        </dia:attribute>
-        <dia:attribute name="width_y">
-          <dia:real val="1"/>
-        </dia:attribute>
-        <dia:attribute name="visible_x">
-          <dia:int val="1"/>
-        </dia:attribute>
-        <dia:attribute name="visible_y">
-          <dia:int val="1"/>
-        </dia:attribute>
-        <dia:composite type="color"/>
-      </dia:composite>
-    </dia:attribute>
-    <dia:attribute name="color">
-      <dia:color val="#d8e5e5"/>
-    </dia:attribute>
-    <dia:attribute name="guides">
-      <dia:composite type="guides">
-        <dia:attribute name="hguides"/>
-        <dia:attribute name="vguides"/>
-      </dia:composite>
-    </dia:attribute>
-  </dia:diagramdata>
-  <dia:layer name="New layer 1" visible="true" active="true">
-    <dia:object type="Standard - Box" version="0" id="O0">
-      <dia:attribute name="obj_pos">
-        <dia:point val="13.1551,5.70485"/>
-      </dia:attribute>
-      <dia:attribute name="obj_bb">
-        <dia:rectangle val="13.1051,5.65485;29.4092,11.5949"/>
-      </dia:attribute>
-      <dia:attribute name="elem_corner">
-        <dia:point val="13.1551,5.70485"/>
-      </dia:attribute>
-      <dia:attribute name="elem_width">
-        <dia:real val="16.204140120230058"/>
-      </dia:attribute>
-      <dia:attribute name="elem_height">
-        <dia:real val="5.8400708047529699"/>
-      </dia:attribute>
-      <dia:attribute name="border_width">
-        <dia:real val="0.10000000149011612"/>
-      </dia:attribute>
-      <dia:attribute name="border_color">
-        <dia:color val="#ffff00"/>
-      </dia:attribute>
-      <dia:attribute name="inner_color">
-        <dia:color val="#ffff00"/>
-      </dia:attribute>
-      <dia:attribute name="show_background">
-        <dia:boolean val="true"/>
-      </dia:attribute>
-    </dia:object>
-    <dia:group>
-      <dia:object type="Standard - Box" version="0" id="O1">
-        <dia:attribute name="obj_pos">
-          <dia:point val="13.5072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="13.4572,6.02489;17.3572,11.2249"/>
-        </dia:attribute>
-        <dia:attribute name="elem_corner">
-          <dia:point val="13.5072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="elem_width">
-          <dia:real val="3.8000000000000007"/>
-        </dia:attribute>
-        <dia:attribute name="elem_height">
-          <dia:real val="5.0999999999999996"/>
-        </dia:attribute>
-        <dia:attribute name="border_width">
-          <dia:real val="0.10000000149011612"/>
-        </dia:attribute>
-        <dia:attribute name="border_color">
-          <dia:color val="#cbd4fa"/>
-        </dia:attribute>
-        <dia:attribute name="inner_color">
-          <dia:color val="#cbd4fa"/>
-        </dia:attribute>
-        <dia:attribute name="show_background">
-          <dia:boolean val="true"/>
-        </dia:attribute>
-      </dia:object>
-      <dia:object type="Standard - Box" version="0" id="O2">
-        <dia:attribute name="obj_pos">
-          <dia:point val="17.4072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="17.3572,6.02489;21.2572,11.2249"/>
-        </dia:attribute>
-        <dia:attribute name="elem_corner">
-          <dia:point val="17.4072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="elem_width">
-          <dia:real val="3.8000000000000007"/>
-        </dia:attribute>
-        <dia:attribute name="elem_height">
-          <dia:real val="5.0999999999999996"/>
-        </dia:attribute>
-        <dia:attribute name="border_width">
-          <dia:real val="0.10000000149011612"/>
-        </dia:attribute>
-        <dia:attribute name="border_color">
-          <dia:color val="#90a5fe"/>
-        </dia:attribute>
-        <dia:attribute name="inner_color">
-          <dia:color val="#90a5fe"/>
-        </dia:attribute>
-        <dia:attribute name="show_background">
-          <dia:boolean val="true"/>
-        </dia:attribute>
-      </dia:object>
-      <dia:object type="Standard - Box" version="0" id="O3">
-        <dia:attribute name="obj_pos">
-          <dia:point val="21.3072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="21.2572,6.02489;25.1572,11.2249"/>
-        </dia:attribute>
-        <dia:attribute name="elem_corner">
-          <dia:point val="21.3072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="elem_width">
-          <dia:real val="3.8000000000000007"/>
-        </dia:attribute>
-        <dia:attribute name="elem_height">
-          <dia:real val="5.0999999999999996"/>
-        </dia:attribute>
-        <dia:attribute name="border_width">
-          <dia:real val="0.10000000149011612"/>
-        </dia:attribute>
-        <dia:attribute name="border_color">
-          <dia:color val="#5e78f6"/>
-        </dia:attribute>
-        <dia:attribute name="inner_color">
-          <dia:color val="#5e78f6"/>
-        </dia:attribute>
-        <dia:attribute name="show_background">
-          <dia:boolean val="true"/>
-        </dia:attribute>
-      </dia:object>
-      <dia:object type="Standard - Box" version="0" id="O4">
-        <dia:attribute name="obj_pos">
-          <dia:point val="25.2072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="25.1572,6.02489;29.0572,11.2249"/>
-        </dia:attribute>
-        <dia:attribute name="elem_corner">
-          <dia:point val="25.2072,6.07489"/>
-        </dia:attribute>
-        <dia:attribute name="elem_width">
-          <dia:real val="3.8000000000000007"/>
-        </dia:attribute>
-        <dia:attribute name="elem_height">
-          <dia:real val="5.0999999999999996"/>
-        </dia:attribute>
-        <dia:attribute name="border_width">
-          <dia:real val="0.10000000149011612"/>
-        </dia:attribute>
-        <dia:attribute name="border_color">
-          <dia:color val="#0000ff"/>
-        </dia:attribute>
-        <dia:attribute name="inner_color">
-          <dia:color val="#0910f4"/>
-        </dia:attribute>
-        <dia:attribute name="show_background">
-          <dia:boolean val="true"/>
-        </dia:attribute>
-      </dia:object>
-      <dia:group>
-        <dia:group>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O5">
-            <dia:attribute name="obj_pos">
-              <dia:point val="25.3046,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="25.2546,9.69613;25.7177,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="25.3046,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O6">
-            <dia:attribute name="obj_pos">
-              <dia:point val="25.7677,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="25.7177,9.69613;26.1809,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="25.7677,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O7">
-            <dia:attribute name="obj_pos">
-              <dia:point val="26.2309,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="26.1809,9.69613;26.644,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="26.2309,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O8">
-            <dia:attribute name="obj_pos">
-              <dia:point val="26.694,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="26.644,9.69613;27.1072,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="26.694,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O9">
-            <dia:attribute name="obj_pos">
-              <dia:point val="27.1572,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="27.1072,9.69613;27.5703,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="27.1572,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O10">
-            <dia:attribute name="obj_pos">
-              <dia:point val="27.6203,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="27.5703,9.69613;28.0335,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="27.6203,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O11">
-            <dia:attribute name="obj_pos">
-              <dia:point val="28.0835,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="28.0335,9.69613;28.4966,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="28.0835,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O12">
-            <dia:attribute name="obj_pos">
-              <dia:point val="28.5466,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="28.4966,9.69613;28.9598,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="28.5466,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-        </dia:group>
-        <dia:group>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O13">
-            <dia:attribute name="obj_pos">
-              <dia:point val="21.8026,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="21.7526,9.69613;22.2157,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="21.8026,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O14">
-            <dia:attribute name="obj_pos">
-              <dia:point val="22.6179,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="22.5679,9.69613;23.0311,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="22.6179,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O15">
-            <dia:attribute name="obj_pos">
-              <dia:point val="23.4333,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="23.3833,9.69613;23.8464,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="23.4333,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O16">
-            <dia:attribute name="obj_pos">
-              <dia:point val="24.2486,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="24.1986,9.69613;24.6618,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="24.2486,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-        </dia:group>
-        <dia:object type="Geometric - Perfect Circle" version="1" id="O17">
-          <dia:attribute name="obj_pos">
-            <dia:point val="15.2256,9.74613"/>
-          </dia:attribute>
-          <dia:attribute name="obj_bb">
-            <dia:rectangle val="15.1756,9.69613;15.6388,10.1593"/>
-          </dia:attribute>
-          <dia:attribute name="meta">
-            <dia:composite type="dict"/>
-          </dia:attribute>
-          <dia:attribute name="elem_corner">
-            <dia:point val="15.2256,9.74613"/>
-          </dia:attribute>
-          <dia:attribute name="elem_width">
-            <dia:real val="0.3631490811886362"/>
-          </dia:attribute>
-          <dia:attribute name="elem_height">
-            <dia:real val="0.3631490811886362"/>
-          </dia:attribute>
-          <dia:attribute name="line_width">
-            <dia:real val="0.10000000149011612"/>
-          </dia:attribute>
-          <dia:attribute name="line_colour">
-            <dia:color val="#000000"/>
-          </dia:attribute>
-          <dia:attribute name="fill_colour">
-            <dia:color val="#ff0000"/>
-          </dia:attribute>
-          <dia:attribute name="show_background">
-            <dia:boolean val="true"/>
-          </dia:attribute>
-          <dia:attribute name="line_style">
-            <dia:enum val="0"/>
-            <dia:real val="1"/>
-          </dia:attribute>
-          <dia:attribute name="flip_horizontal">
-            <dia:boolean val="false"/>
-          </dia:attribute>
-          <dia:attribute name="flip_vertical">
-            <dia:boolean val="false"/>
-          </dia:attribute>
-          <dia:attribute name="subscale">
-            <dia:real val="1"/>
-          </dia:attribute>
-        </dia:object>
-        <dia:group>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O18">
-            <dia:attribute name="obj_pos">
-              <dia:point val="18.3889,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="18.3389,9.69613;18.8021,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="18.3889,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.3631490811886362"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-          <dia:object type="Geometric - Perfect Circle" version="1" id="O19">
-            <dia:attribute name="obj_pos">
-              <dia:point val="19.8623,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="obj_bb">
-              <dia:rectangle val="19.8123,9.69613;20.2754,10.1593"/>
-            </dia:attribute>
-            <dia:attribute name="meta">
-              <dia:composite type="dict"/>
-            </dia:attribute>
-            <dia:attribute name="elem_corner">
-              <dia:point val="19.8623,9.74613"/>
-            </dia:attribute>
-            <dia:attribute name="elem_width">
-              <dia:real val="0.36314908118863798"/>
-            </dia:attribute>
-            <dia:attribute name="elem_height">
-              <dia:real val="0.36314908118863798"/>
-            </dia:attribute>
-            <dia:attribute name="line_width">
-              <dia:real val="0.10000000149011612"/>
-            </dia:attribute>
-            <dia:attribute name="line_colour">
-              <dia:color val="#000000"/>
-            </dia:attribute>
-            <dia:attribute name="fill_colour">
-              <dia:color val="#ff0000"/>
-            </dia:attribute>
-            <dia:attribute name="show_background">
-              <dia:boolean val="true"/>
-            </dia:attribute>
-            <dia:attribute name="line_style">
-              <dia:enum val="0"/>
-              <dia:real val="1"/>
-            </dia:attribute>
-            <dia:attribute name="flip_horizontal">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="flip_vertical">
-              <dia:boolean val="false"/>
-            </dia:attribute>
-            <dia:attribute name="subscale">
-              <dia:real val="1"/>
-            </dia:attribute>
-          </dia:object>
-        </dia:group>
-      </dia:group>
-      <dia:object type="Standard - Line" version="0" id="O20">
-        <dia:attribute name="obj_pos">
-          <dia:point val="14.4506,9.23568"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="14.4006,8.90478;28.1138,9.56659"/>
-        </dia:attribute>
-        <dia:attribute name="conn_endpoints">
-          <dia:point val="14.4506,9.23568"/>
-          <dia:point val="28.002,9.23568"/>
-        </dia:attribute>
-        <dia:attribute name="numcp">
-          <dia:int val="1"/>
-        </dia:attribute>
-        <dia:attribute name="line_color">
-          <dia:color val="#ffffff"/>
-        </dia:attribute>
-        <dia:attribute name="line_width">
-          <dia:real val="0.10000000000000001"/>
-        </dia:attribute>
-        <dia:attribute name="end_arrow">
-          <dia:enum val="3"/>
-        </dia:attribute>
-        <dia:attribute name="end_arrow_length">
-          <dia:real val="0.5"/>
-        </dia:attribute>
-        <dia:attribute name="end_arrow_width">
-          <dia:real val="0.5"/>
-        </dia:attribute>
-      </dia:object>
-      <dia:object type="Standard - Text" version="1" id="O21">
-        <dia:attribute name="obj_pos">
-          <dia:point val="19.8922,8.37201"/>
-        </dia:attribute>
-        <dia:attribute name="obj_bb">
-          <dia:rectangle val="19.8922,6.86701;22.6222,8.68701"/>
-        </dia:attribute>
-        <dia:attribute name="text">
-          <dia:composite type="text">
-            <dia:attribute name="string">
-              <dia:string>#DSS#</dia:string>
-            </dia:attribute>
-            <dia:attribute name="font">
-              <dia:font family="Serif" style="80" name="Times-Bold"/>
-            </dia:attribute>
-            <dia:attribute name="height">
-              <dia:real val="1.8584333549302243"/>
-            </dia:attribute>
-            <dia:attribute name="pos">
-              <dia:point val="19.8922,8.37201"/>
-            </dia:attribute>
-            <dia:attribute name="color">
-              <dia:color val="#ffffff"/>
-            </dia:attribute>
-            <dia:attribute name="alignment">
-              <dia:enum val="0"/>
-            </dia:attribute>
-          </dia:composite>
-        </dia:attribute>
-        <dia:attribute name="valign">
-          <dia:enum val="3"/>
-        </dia:attribute>
-      </dia:object>
-    </dia:group>
-  </dia:layer>
-</dia:diagram>
index d4926c3117ab214461d44b359beb02e77bfcd9f5..f02c825223d55aaf7275a567ef93a352a7523bf5 100644 (file)
--- a/dss.suite
+++ b/dss.suite
@@ -34,7 +34,7 @@ caption = Subcommands
                        However, there is one exception to this rule: The run subcommand
                        re-reads the configuration file when it receives the HUP signal. In
                        this case the options in the config file override any options that
-                       were previously given at the command line. This allows to change the
+                       were previously given at the command line. This allows changing the
                        configuration of a running dss process by sending SIGHUP.
                [/help]
        [option loglevel]
@@ -79,6 +79,18 @@ caption = Subcommands
 
                        This option is mandatory for all subcommands except kill.
                [/help]
+       [option mountpoint]
+               summary = abort if destination directory is not a mountpoint
+               [help]
+                       This option checks whether a file system is mounted on the directory
+                       specified as the argument to --dest-dir. Operation proceeds only
+                       if this is the case. Otherwise dss exits unsuccessfully without
+                       performing any action. Use this option to prevent snapshot creation
+                       if the snapshot file system is not mounted.
+
+                       This option is silently ignored for subcommands which do not depend
+                       on the destination directory.
+               [/help]
        [option Rsync-options]
                summary = Controlling how rsync is run
                flag ignored
@@ -312,8 +324,8 @@ caption = Subcommands
                typestr = percent
                default_val = 2
                [help]
-                       This is like --min-free-mb but allows to specify the amount of
-                       free disk space as a percentage. It is not recommended to set both
+                       This is like --min-free-mb but the amount of free disk space
+                       is specified as a percentage. It is not recommended to set both
                        --min-free-mb and --min-free-percent to zero as this will cause your
                        file system to fill up quickly.
                [/help]
@@ -496,6 +508,14 @@ caption = Subcommands
 
                        It makes only sense to use the option for signals which terminate dss.
                [/help]
+[subcommand configtest]
+       purpose = run a configuration file syntax test
+       [description]
+               This command checks the command line options and the configuration
+               file for syntactic correctness. It either reports "Syntax Ok" and
+               exits successfully or prints information about the first syntax error
+               detected and terminates with exit code 1.
+       [/description]
 
 [section copyright]
        Written by Andre Noll
diff --git a/err.h b/err.h
index c3e207edf4ac076f4d6162cd8925e59dbca1bc0f..2280010a39764156dbb25a13a0653db6f2681a81 100644 (file)
--- a/err.h
+++ b/err.h
@@ -48,6 +48,7 @@ static inline char *dss_strerror(int num)
        DSS_ERROR(INVALID_NUMBER, "invalid number"), \
        DSS_ERROR(STRFTIME, "strftime() failed"), \
        DSS_ERROR(LOCALTIME, "localtime() failed"), \
+       DSS_ERROR(MOUNTPOINT, "destination directory is no mountpoint"), \
        DSS_ERROR(NULL_OPEN, "can not open /dev/null"), \
        DSS_ERROR(DUP_PIPE, "exec error: can not create pipe"), \
        DSS_ERROR(INVOLUNTARY_EXIT, "unexpected termination cause"), \
diff --git a/file.h b/file.h
index 140a505ba01b1fe3adb3614e118103517a722384..f82643a57fe961d3d1f67c837b69f794670188d0 100644 (file)
--- a/file.h
+++ b/file.h
@@ -5,17 +5,7 @@
  */
 int for_each_subdir(int (*func)(const char *, void *), void *private_data);
 __must_check int mark_fd_nonblocking(int fd);
-/**
- * A wrapper for rename(2).
- *
- * \param old_path The source path.
- * \param new_path The destination path.
- *
- * \return Standard.
- *
- * \sa rename(2).
- */
-_static_inline_ int dss_rename(const char *old_path, const char *new_path)
+static inline int dss_rename(const char *old_path, const char *new_path)
 {
        if (rename(old_path, new_path) >= 0)
                return 1;
index a15b0cef5c0f4b10672ab8a620429438baa1e1c2..258a3cb279b7e9045da566a17f9f7d8f52f6b40d 100644 (file)
@@ -2,24 +2,12 @@
        defined(__GNUC__) && \
        (__GNUC__ > maj || (__GNUC__ == maj && __GNUC_MINOR__ >= min))
 
-#if HAVE_GNUC(2,5)
-# define __noreturn    __attribute__ ((noreturn))
-#else
-# define __noreturn
-#endif
-
 #if HAVE_GNUC(3,0)
 # define __malloc      __attribute__ ((malloc))
 #else
 # define __malloc
 #endif
 
-#if HAVE_GNUC(2,7)
-# define __a_unused    __attribute__ ((unused))
-#else
-# define __a_unused
-#endif
-
 /* 
  * p is the number of the "format string" parameter, and q is 
  * the number of the first variadic parameter 
 # define __printf(p,q)
 #endif
 
-/*
- * as direct use of __printf(p,q) confuses doxygen, here are two extra macros
- * for those values p,q that are actually used by paraslash.
- */
 #define  __printf_1_2 __printf(1,2)
-#define  __printf_2_3 __printf(2,3)
 
 #if HAVE_GNUC(3,3)
 # define __must_check  __attribute__ ((warn_unused_result))
 #else
 # define __must_check  /* no warn_unused_result */
 #endif
-
-#define _static_inline_ static inline
diff --git a/mklogo b/mklogo
new file mode 100755 (executable)
index 0000000..54c8c95
--- /dev/null
+++ b/mklogo
@@ -0,0 +1,100 @@
+#!/bin/bash
+
+# Script for Image Magick that writes the dss logo in png format
+# to stdout.
+
+set -u
+
+width=320
+height=110
+border=5
+radius1=4
+radius2=5
+circle_y=90
+arrow_y=70
+text_x=128
+text_y=55
+pointsize=36
+
+declare -a circle arrow rectangle text
+
+make_circles()
+{
+       local inner='stroke black fill red circle'
+       local outer='stroke black fill black circle'
+       local num=1
+       local idx=0
+       local y=$circle_y
+       local step x0 i j idx num
+
+       for ((i = 0; i < 4; i++)); do
+               step=$(((width / 4 + num) / (num + 1)))
+               x0=$((border + width / 4 * i))
+               for ((j = 1; j <= $num; j++)); do
+                       x=$((x0 + j * $step))
+                       circle[$idx]='-draw'; let idx++
+                       circle[$idx]="$outer $x,$y,$((x + radius2)),$y"; let idx++
+                       circle[$idx]='-draw'; let idx++
+                       circle[$idx]="$inner $x,$y,$((x + radius1)),$y"; let idx++
+               done
+               num=$((num * 2))
+       done
+       #echo "${circle[@]}"; exit 0
+}
+
+make_arrow()
+{
+       local arrow_head='l -15,-5  +5,+5  -5,+5  +15,-5 z'
+       local idx=0
+       local x0 x1 y
+
+       arrow[$idx]='-draw'; let idx++
+       x0=$((3 * border)); x1=$((width - 2 * border))
+       y=$arrow_y
+       arrow[$idx]="stroke white line $x0,$y $x1,$y"; let idx++
+       arrow[$idx]='-draw'; let idx++
+       x0=$((width - 2 * border))
+       arrow[$idx]="stroke white fill white path 'M $x0,$y $arrow_head'"
+       #echo "${arrow[@]}"; exit 0
+}
+
+make_rectangles()
+{
+       local idx=0
+       local x x0 x1 y y0 y1 i red_green color
+
+       rectangle[$idx]='-draw'; let idx++
+       x=$((width + 2 * border))
+       y=$((height + 2 * border))
+       rectangle[$idx]="stroke yellow fill yellow rectangle 0,0 $x,$y"; let idx++
+       for ((i = 0; i < 4; i++)); do
+               rectangle[$idx]='-draw'; let idx++
+               red_green="$(printf '%02x' $(((3 - i) * 60)))"
+               color="#${red_green}${red_green}ff"
+               x0=$((border + i * width / 4)); x1=$((x0 + width / 4 - 1))
+               y0=$border; y1=$((y0 + height))
+               rectangle[$idx]="stroke $color fill $color rectangle $x0,$y0 $x1,$y1"
+               let idx++
+       done
+       #echo "${rectangle[@]}"; exit 0
+}
+
+make_text()
+{
+       text=(-pointsize $pointsize -draw \
+               "fill white text $text_x,$text_y DSS")
+       #echo "${text[@]}"; exit 0
+}
+
+make_rectangles
+make_arrow
+make_circles
+make_text
+
+convert -size $((width + 2 * border))x$((height + 2 * border)) \
+       -background none xc: \
+       "${rectangle[@]}" \
+       "${arrow[@]}" \
+       "${circle[@]}" \
+       "${text[@]}" \
+       png:-
diff --git a/snap.h b/snap.h
index 626ecad003a52a1a465ea6f7f2e11f960a97df3c..489b67a2fbbb39f69533e50bfc996b1c7db20525 100644 (file)
--- a/snap.h
+++ b/snap.h
@@ -93,7 +93,7 @@ int num_complete_snapshots(struct snapshot_list *sl);
 /**
  * Get the newest snapshot in a snapshot list.
  */
-_static_inline_ struct snapshot *get_newest_snapshot(struct snapshot_list *sl)
+static inline struct snapshot *get_newest_snapshot(struct snapshot_list *sl)
 {
        if (!sl->num_snapshots)
                return NULL;
diff --git a/tv.c b/tv.c
index 8ab5e5a90a6bd151c87750adb761c135b7ec774e..f954cef0c9a1342fedc4d2a49851ad56ca11aa9e 100644 (file)
--- a/tv.c
+++ b/tv.c
@@ -54,6 +54,5 @@ int64_t get_current_time(void)
 {
        time_t now;
        time(&now);
-       DSS_DEBUG_LOG(("now: %jd\n", (intmax_t)now));
        return (int64_t)now;
 }