Welcome to little lamb

Code » anopa » commit f1b36d5

enable: Add -/+ to remove/append to files from listdir

author Olivier Brunel
2015-03-16 17:53:09 UTC
committer Olivier Brunel
2015-04-04 12:47:36 UTC
parent a6ffa900d6e8d26976943445e970aa601f300709

enable: Add -/+ to remove/append to files from listdir

Files in listdir starting with a '-' can be used to remove files from
the newly created servicedir; Files starting with a '+' will have their
content appended to the file (minus the '+') in servicedir.

doc/aa-enable.pod +14 -1
src/include/anopa/copy_file.h +9 -1
src/include/anopa/enable_service.h +4 -3
src/libanopa/copy_file.c +8 -2
src/libanopa/enable_service.c +22 -4
src/utils/aa-mvlog.c +1 -1

diff --git a/doc/aa-enable.pod b/doc/aa-enable.pod
index 46ca81f..4a271e9 100644
--- a/doc/aa-enable.pod
+++ b/doc/aa-enable.pod
@@ -110,7 +110,8 @@ this is a long-run or one-shot service.
 
 - If the service name came from a directory in I<LISTDIR>, its content is then
 merged/copied over into the servicedir. This allows to specify service-specific
-configuration, or could possibly be used to overwrite an actual script.
+configuration, or could possibly be used to overwrite an actual script. See
+below for how to remove/append to files.
 
 - If the service is a long-run, an empty regular file I<down> is created (unless
 it already existed, or the service was specified to B<--skip-down>) to ensure
@@ -160,3 +161,15 @@ source directory); Or use a directory to simply specify/add configuration files.
 Note that you can also still provide files from the configuration directory in
 listdir, since it is copied last (and that this always includes providing a new
 I<run> file).
+
+=head2 Removing/appending to files
+
+When copying files from the "configuration directory" (directory in I<LISTDIR>)
+regular files starting with either a dash ( - ) or plus sign ( + ) are processed
+in a special manner:
+
+- A file I<-foobar> will have B<aa-enable>(1) remove file I<foobar> from the
+destination servicedir, if it exists.
+
+- A file I<+foobar> will have its content be appended to I<foobar> in the
+destination servicedir.
diff --git a/src/include/anopa/copy_file.h b/src/include/anopa/copy_file.h
index 9210255..90fb671 100644
--- a/src/include/anopa/copy_file.h
+++ b/src/include/anopa/copy_file.h
@@ -2,6 +2,14 @@
 #ifndef AA_COPY_FILE_H
 #define AA_COPY_FILE_H
 
-int aa_copy_file (const char *src, const char *dst, mode_t mode, int overwrite);
+typedef enum
+{
+    AA_CP_CREATE = 0,
+    AA_CP_OVERWRITE,
+    AA_CP_APPEND,
+    _AA_CP_NB
+} aa_cp;
+
+int aa_copy_file (const char *src, const char *dst, mode_t mode, aa_cp cp);
 
 #endif /* AA_COPY_FILE_H */
diff --git a/src/include/anopa/enable_service.h b/src/include/anopa/enable_service.h
index 11031ec..9e38388 100644
--- a/src/include/anopa/enable_service.h
+++ b/src/include/anopa/enable_service.h
@@ -12,9 +12,10 @@ typedef enum
     AA_FLAG_SKIP_DOWN           = (1 << 2),
     /* private */
     _AA_FLAG_IS_SERVICEDIR      = (1 << 3),
-    _AA_FLAG_IS_NEEDS           = (1 << 4),
-    _AA_FLAG_IS_WANTS           = (1 << 5),
-    _AA_FLAG_IS_BEF_AFT         = (1 << 6),
+    _AA_FLAG_IS_CONFIGDIR       = (1 << 4),
+    _AA_FLAG_IS_NEEDS           = (1 << 5),
+    _AA_FLAG_IS_WANTS           = (1 << 6),
+    _AA_FLAG_IS_BEF_AFT         = (1 << 7),
     _AA_FLAG_IS_1OF4            = _AA_FLAG_IS_NEEDS | _AA_FLAG_IS_WANTS | _AA_FLAG_IS_BEF_AFT
 } aa_enable_flags;
 
diff --git a/src/libanopa/copy_file.c b/src/libanopa/copy_file.c
index 17275a7..dc6771a 100644
--- a/src/libanopa/copy_file.c
+++ b/src/libanopa/copy_file.c
@@ -2,18 +2,24 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <skalibs/djbunix.h>
+#include <anopa/copy_file.h>
 
 int
-aa_copy_file (const char *src, const char *dst, mode_t mode, int overwrite)
+aa_copy_file (const char *src, const char *dst, mode_t mode, aa_cp cp)
 {
     int fd_src;
     int fd_dst;
+    int flag[_AA_CP_NB];
 
     fd_src = open_readb (src);
     if (fd_src < 0)
         return -1;
 
-    fd_dst = open3 (dst, O_WRONLY | O_CREAT | ((overwrite) ? O_TRUNC : O_EXCL), mode);
+    flag[AA_CP_CREATE] = O_EXCL;
+    flag[AA_CP_OVERWRITE] = O_TRUNC;
+    flag[AA_CP_APPEND] = O_APPEND;
+
+    fd_dst = open3 (dst, O_WRONLY | O_CREAT | flag[cp], mode);
     if (fd_dst < 0)
     {
         int e = errno;
diff --git a/src/libanopa/enable_service.c b/src/libanopa/enable_service.c
index 9336831..e0d3922 100644
--- a/src/libanopa/enable_service.c
+++ b/src/libanopa/enable_service.c
@@ -201,6 +201,23 @@ copy_dir (const char        *src,
                     r = copy_log (dst, NULL, 0, warn_fn);
                     st.st_mode = 0755;
                 }
+                else if ((flags & _AA_FLAG_IS_CONFIGDIR) && len > 1
+                        && (satmp.s[i] == '-' || satmp.s[i] == '+'))
+                {
+                    byte_copy (buf_dst + l_dst + 1, len, satmp.s + i + 1);
+
+                    if (satmp.s[i] == '-')
+                    {
+                        r = unlink (buf_dst);
+                        if (r < 0 && errno == ENOENT)
+                            /* not an error */
+                            r = 0;
+                        /* skip lchown/chmod calls */
+                        goto next;
+                    }
+                    else /* '+' */
+                        r = aa_copy_file (buf_src, buf_dst, st.st_mode, AA_CP_APPEND);
+                }
                 else
                 {
                     /* for any file in one of the 4 special places that ends
@@ -208,7 +225,7 @@ copy_dir (const char        *src,
                     if (depth == 1 && instance && (flags & _AA_FLAG_IS_1OF4)
                             && satmp.s[i + len - 1] == '@')
                         byte_copy (buf_dst + l_dst + 1 + len, l_inst + 1, instance);
-                    r = aa_copy_file (buf_src, buf_dst, st.st_mode, 1);
+                    r = aa_copy_file (buf_src, buf_dst, st.st_mode, AA_CP_OVERWRITE);
                     if (depth == 1 && r == 0 && ae_cb)
                     {
                         if ((flags & (AA_FLAG_AUTO_ENABLE_NEEDS | _AA_FLAG_IS_NEEDS))
@@ -270,6 +287,7 @@ copy_dir (const char        *src,
             if (r >= 0 && !S_ISLNK (st.st_mode) && !S_ISDIR (st.st_mode))
                 r = chmod (buf_dst, st.st_mode);
 
+next:
             if (r < 0)
             {
                 warn_fn (buf_src, errno);
@@ -457,7 +475,7 @@ aa_enable_service (const char       *_name,
         return r;
 
     if (name != _name)
-        return copy_dir (_name, name, _mode, 0, warn_fn, flags, ae_cb, instance);
-    else
-        return 0;
+        r = copy_dir (_name, name, _mode, 0, warn_fn, flags | _AA_FLAG_IS_CONFIGDIR, ae_cb, instance);
+
+    return r;
 }
diff --git a/src/utils/aa-mvlog.c b/src/utils/aa-mvlog.c
index cc55d53..6aec2fe 100644
--- a/src/utils/aa-mvlog.c
+++ b/src/utils/aa-mvlog.c
@@ -54,7 +54,7 @@ main (int argc, char * const argv[])
             strerr_dief2x (2, "invalid new name read from ", argv[1]);
         newname[l + 26] = '\0';
 
-        if (aa_copy_file (argv[1], newname, st.st_mode, 0) < 0)
+        if (aa_copy_file (argv[1], newname, st.st_mode, AA_CP_CREATE) < 0)
             strerr_diefu4sys (2, "copy ", argv[1], " as ", newname);
 
         byte_copy (target, 26, newname + l + 1);