Blob Blame History Raw
From 3ed08d1e4dbb52dc181be01b6e147017327aa6d9 Mon Sep 17 00:00:00 2001
From: Harald Hoyer <harald@redhat.com>
Date: Mon, 29 Apr 2013 11:35:23 +0200
Subject: [PATCH] dracut-install: make use of _cleanup_* macros

---
 install/dracut-install.c | 230 +++++++++++++++++++++++++----------------------
 install/macro.h          | 150 +++++++++++++++++++++++++------
 install/util.h           |  36 ++++++++
 3 files changed, 281 insertions(+), 135 deletions(-)

diff --git a/install/dracut-install.c b/install/dracut-install.c
index 2fad6df..b4bf681 100644
--- a/install/dracut-install.c
+++ b/install/dracut-install.c
@@ -62,6 +62,10 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
 static size_t dir_len(char const *file)
 {
         size_t length;
+
+        if(!file)
+                return 0;
+
         /* Strip the basename and any redundant slashes before it.  */
         for (length = strlen(file)-1; 0 < length; length--)
                 if (file[length] == '/' && file[length-1] != '/')
@@ -73,20 +77,22 @@ static char *convert_abs_rel(const char *from, const char *target)
 {
         /* we use the 4*MAXPATHLEN, which should not overrun */
         char relative_from[MAXPATHLEN * 4];
-        char *realtarget = NULL;
-        char *p, *q;
+        _cleanup_free_ char *realtarget = NULL;
+        _cleanup_free_ char *target_dir_p = NULL, *realpath_p = NULL;
         const char *realfrom = from;
         int level = 0, fromlevel = 0, targetlevel = 0;
         int l, i, rl;
         int dirlen;
 
-        p = strdup(target);
-        dirlen = dir_len(p);
-        p[dirlen] = '\0';
-        q = realpath(p, NULL);
+        target_dir_p = strdup(target);
+        if (!target_dir_p)
+                return strdup(from);
+
+        dirlen = dir_len(target_dir_p);
+        target_dir_p[dirlen] = '\0';
+        realpath_p = realpath(target_dir_p, NULL);
 
-        if (q == NULL) {
-                free(p);
+        if (realpath_p == NULL) {
                 log_warning("convert_abs_rel(): target '%s' directory has no realpath.", target);
                 return strdup(from);
         }
@@ -95,11 +101,9 @@ static char *convert_abs_rel(const char *from, const char *target)
          * character - need to skip all leading /'s */
         rl = strlen(target);
         for (i = dirlen+1; i < rl; ++i)
-            if (p[i] != '/')
+            if (target_dir_p[i] != '/')
                 break;
-        asprintf(&realtarget, "%s/%s", q, &p[i]);
-        free(p);
-        free(q);
+        asprintf(&realtarget, "%s/%s", realpath_p, &target_dir_p[i]);
 
         /* now calculate the relative path from <from> to <target> and
            store it in <relative_from>
@@ -122,8 +126,6 @@ static char *convert_abs_rel(const char *from, const char *target)
                 if (realtarget[i] == '/')
                         level++;
 
-        free(realtarget);
-
         /* add "../" to the relative_from path, until the common pathname is
            reached */
         for (i = level; i < targetlevel; i++) {
@@ -155,18 +157,16 @@ static char *convert_abs_rel(const char *from, const char *target)
 static int ln_r(const char *src, const char *dst)
 {
         int ret;
-        const char *points_to = convert_abs_rel(src, dst);
+        _cleanup_free_ const char *points_to = convert_abs_rel(src, dst);
+
         log_info("ln -s '%s' '%s'", points_to, dst);
         ret = symlink(points_to, dst);
 
         if (ret != 0) {
                 log_error("ERROR: ln -s '%s' '%s': %m", points_to, dst);
-                free((char *)points_to);
                 return 1;
         }
 
-        free((char *)points_to);
-
         return 0;
 }
 
@@ -186,11 +186,11 @@ static bool use_clone = true;
 static int cp(const char *src, const char *dst)
 {
         int pid;
-        int ret;
+        int ret = 0;
 
         if (use_clone) {
                 struct stat sb;
-                int dest_desc, source_desc;
+                _cleanup_close_ int dest_desc = -1, source_desc = -1;
 
                 if (lstat(src, &sb) != 0)
                         goto normal_copy;
@@ -207,12 +207,11 @@ static int cp(const char *src, const char *dst)
                          (sb.st_mode) & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO));
 
                 if (dest_desc < 0) {
-                        close(source_desc);
                         goto normal_copy;
                 }
 
                 ret = clone_file(dest_desc, source_desc);
-                close(source_desc);
+
                 if (ret == 0) {
                         struct timeval tv[2];
                         if (fchown(dest_desc, sb.st_uid, sb.st_gid) != 0)
@@ -222,11 +221,10 @@ static int cp(const char *src, const char *dst)
                         tv[1].tv_sec = sb.st_mtime;
                         tv[1].tv_usec = 0;
                         futimes(dest_desc, tv);
-                        close(dest_desc);
                         return ret;
                 }
                 close(dest_desc);
-
+                dest_desc = -1;
                 /* clone did not work, remove the file */
                 unlink(dst);
                 /* do not try clone again */
@@ -243,10 +241,11 @@ static int cp(const char *src, const char *dst)
         while (waitpid(pid, &ret, 0) < 0) {
                 if (errno != EINTR) {
                         ret = -1;
+                        log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,timestamps -fL %s %s", src, dst);
                         break;
                 }
         }
-
+        log_debug("cp ret = %d", ret);
         return ret;
 }
 
@@ -256,15 +255,17 @@ static int resolve_deps(const char *src)
 
         char *buf = malloc(LINE_MAX);
         size_t linesize = LINE_MAX;
-        FILE *fptr;
-        char *cmd;
+        _cleanup_pclose_ FILE *fptr = NULL;
+        _cleanup_free_ char *cmd = NULL;
 
         if (strstr(src, ".so") == 0) {
-                int fd;
+                _cleanup_close_ int fd = -1;
                 fd = open(src, O_RDONLY | O_CLOEXEC);
+                if (fd < 0)
+                        return -errno;
+
                 read(fd, buf, LINE_MAX);
                 buf[LINE_MAX - 1] = '\0';
-                close(fd);
                 if (buf[0] == '#' && buf[1] == '!') {
                         /* we have a shebang */
                         char *p, *q;
@@ -280,7 +281,11 @@ static int resolve_deps(const char *src)
         }
 
         /* run ldd */
-        asprintf(&cmd, "ldd %s 2>&1", src);
+        ret = asprintf(&cmd, "ldd %s 2>&1", src);
+        if (ret < 0)
+                return ret;
+        ret = 0;
+
         fptr = popen(cmd, "r");
 
         while (!feof(fptr)) {
@@ -336,7 +341,6 @@ static int resolve_deps(const char *src)
                         }
                 }
         }
-        pclose(fptr);
 
         return ret;
 }
@@ -344,10 +348,14 @@ static int resolve_deps(const char *src)
 /* Install ".<filename>.hmac" file for FIPS self-checks */
 static int hmac_install(const char *src, const char *dst, const char *hmacpath)
 {
-        char *srcpath = strdup(src);
-        char *dstpath = strdup(dst);
-        char *srchmacname = NULL;
-        char *dsthmacname = NULL;
+        _cleanup_free_ char *srcpath = strdup(src);
+        _cleanup_free_ char *dstpath = strdup(dst);
+        _cleanup_free_ char *srchmacname = NULL;
+        _cleanup_free_ char *dsthmacname = NULL;
+
+        if (!(srcpath && dstpath))
+                return -ENOMEM;
+
         size_t dlen = dir_len(src);
 
         if (endswith(src, ".hmac"))
@@ -371,22 +379,18 @@ static int hmac_install(const char *src, const char *dst, const char *hmacpath)
         }
         log_debug("hmac cp '%s' '%s')", srchmacname, dsthmacname);
         dracut_install(srchmacname, dsthmacname, false, false, true);
-        free(dsthmacname);
-        free(srchmacname);
-        free(srcpath);
-        free(dstpath);
         return 0;
 }
 
 static int dracut_install(const char *src, const char *dst, bool isdir, bool resolvedeps, bool hashdst)
 {
         struct stat sb, db;
-        char *dname = NULL;
-        char *fulldstpath = NULL;
-        char *fulldstdir = NULL;
+        _cleanup_free_ char *fulldstpath = NULL;
+        _cleanup_free_ char *fulldstdir = NULL;
         int ret;
         bool src_exists = true;
-        char *i, *existing;
+        char *i = NULL;
+        char *existing;
 
         log_debug("dracut_install('%s', '%s')", src, dst);
 
@@ -419,6 +423,9 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
         }
 
         i = strdup(dst);
+        if (!i)
+                return -ENOMEM;
+
         hashmap_put(items, i, i);
 
         asprintf(&fulldstpath, "%s%s", destrootdir, dst);
@@ -437,7 +444,6 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
                 } else
                         log_debug("'%s' already exists", fulldstpath);
 
-                free(fulldstpath);
                 /* dst does already exist */
                 return ret;
         }
@@ -449,6 +455,8 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
         ret = stat(fulldstdir, &db);
 
         if (ret < 0) {
+                _cleanup_free_ char *dname = NULL;
+
                 if (errno != ENOENT) {
                         log_error("ERROR: stat '%s': %m", fulldstdir);
                         return 1;
@@ -456,35 +464,34 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
                 /* create destination directory */
                 log_debug("dest dir '%s' does not exist", fulldstdir);
                 dname = strdup(dst);
+                if (!dname)
+                        return 1;
+
                 dname[dir_len(dname)] = '\0';
                 ret = dracut_install(dname, dname, true, false, true);
 
-                free(dname);
-
                 if (ret != 0) {
                         log_error("ERROR: failed to create directory '%s'", fulldstdir);
-                        free(fulldstdir);
                         return 1;
                 }
         }
 
-        free(fulldstdir);
-
         if (isdir && !src_exists) {
                 log_info("mkdir '%s'", fulldstpath);
-                return mkdir(fulldstpath, 0755);
+                ret = mkdir(fulldstpath, 0755);
+                return ret;
         }
 
         /* ready to install src */
 
         if (S_ISDIR(sb.st_mode)) {
                 log_info("mkdir '%s'", fulldstpath);
-                return mkdir(fulldstpath, sb.st_mode | S_IWUSR);
+                ret = mkdir(fulldstpath, sb.st_mode | S_IWUSR);
+                return ret;
         }
 
         if (S_ISLNK(sb.st_mode)) {
-                char *abspath;
-                char *absdestpath = NULL;
+                _cleanup_free_ char *abspath = NULL;
 
                 abspath = realpath(src, NULL);
 
@@ -502,15 +509,13 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
                 }
 
                 if (lstat(fulldstpath, &sb) != 0) {
+                        _cleanup_free_ char *absdestpath = NULL;
 
                         asprintf(&absdestpath, "%s%s", destrootdir, abspath);
 
                         ln_r(absdestpath, fulldstpath);
-
-                        free(absdestpath);
                 }
 
-                free(abspath);
                 if (arg_hmac) {
                         /* copy .hmac files also */
                         hmac_install(src, dst, NULL);
@@ -528,8 +533,12 @@ static int dracut_install(const char *src, const char *dst, bool isdir, bool res
                 }
         }
 
+        log_debug("dracut_install ret = %d", ret);
         log_info("cp '%s' '%s'", src, fulldstpath);
         ret += cp(src, fulldstpath);
+
+        log_debug("dracut_install ret = %d", ret);
+
         return ret;
 }
 
@@ -540,49 +549,49 @@ static void item_free(char *i)
 }
 
 static void usage(int status)
-{
-        /*                                                                     */
-        printf("\
-Usage: %s -D DESTROOTDIR [OPTION]... -a SOURCE...\n\
-   or: %s -D DESTROOTDIR [OPTION]... SOURCE DEST\n\
-\n\
-Install SOURCE to DEST in DESTROOTDIR with all needed dependencies.\n\
-\n\
-  -D --destrootdir    Install all files to DESTROOTDIR as the root\n\
-  -a --all            Install all SOURCE arguments to DESTROOTDIR\n\
-  -o --optional       If SOURCE does not exist, do not fail\n\
-  -d --dir            SOURCE is a directory\n\
-  -l --ldd            Also install shebang executables and libraries\n\
-  -R --resolvelazy    Only install shebang executables and libraries for all SOURCE files\n\
-  -H --fips           Also install all '.SOURCE.hmac' files\n\
-  -v --verbose        Show more output\n\
-     --debug          Show debug output\n\
-     --version        Show package version\n\
-  -h --help           Show this help\n\
-\n\
-Example:\n\
-# mkdir -p /var/tmp/test-root\n\
-# %s -D /var/tmp/test-root --ldd -a sh tr\n\
-# tree /var/tmp/test-root\n\
-/var/tmp/test-root\n\
-|-- lib64 -> usr/lib64\n\
-`-- usr\n\
-    |-- bin\n\
-    |   |-- bash\n\
-    |   |-- sh -> bash\n\
-    |   `-- tr\n\
-    `-- lib64\n\
-        |-- ld-2.15.90.so\n\
-        |-- ld-linux-x86-64.so.2 -> ld-2.15.90.so\n\
-        |-- libc-2.15.90.so\n\
-        |-- libc.so\n\
-        |-- libc.so.6 -> libc-2.15.90.so\n\
-        |-- libdl-2.15.90.so\n\
-        |-- libdl.so -> libdl-2.15.90.so\n\
-        |-- libdl.so.2 -> libdl-2.15.90.so\n\
-        |-- libtinfo.so.5 -> libtinfo.so.5.9\n\
-        `-- libtinfo.so.5.9\n\
-", program_invocation_short_name, program_invocation_short_name, program_invocation_short_name);
+{        
+             /*                                                                     */
+        printf("Usage: %s -D DESTROOTDIR [OPTION]... -a SOURCE...\n"
+               "or: %s -D DESTROOTDIR [OPTION]... SOURCE DEST\n"
+               "\n"
+               "Install SOURCE to DEST in DESTROOTDIR with all needed dependencies.\n"
+               "\n"
+               "  -D --destrootdir    Install all files to DESTROOTDIR as the root\n"
+               "  -a --all            Install all SOURCE arguments to DESTROOTDIR\n"
+               "  -o --optional       If SOURCE does not exist, do not fail\n"
+               "  -d --dir            SOURCE is a directory\n"
+               "  -l --ldd            Also install shebang executables and libraries\n"
+               "  -R --resolvelazy    Only install shebang executables and libraries\n"
+               "                      for all SOURCE files\n"
+               "  -H --fips           Also install all '.SOURCE.hmac' files\n"
+               "  -v --verbose        Show more output\n"
+               "     --debug          Show debug output\n"
+               "     --version        Show package version\n"
+               "  -h --help           Show this help\n"
+               "\n"
+               "Example:\n"
+               "# mkdir -p /var/tmp/test-root\n"
+               "# %s -D /var/tmp/test-root --ldd -a sh tr\n"
+               "# tree /var/tmp/test-root\n"
+               "/var/tmp/test-root\n"
+               "|-- lib64 -> usr/lib64\n"
+               "`-- usr\n"
+               "    |-- bin\n"
+               "    |   |-- bash\n"
+               "    |   |-- sh -> bash\n"
+               "    |   `-- tr\n"
+               "    `-- lib64\n"
+               "        |-- ld-2.15.90.so\n"
+               "        |-- ld-linux-x86-64.so.2 -> ld-2.15.90.so\n"
+               "        |-- libc-2.15.90.so\n"
+               "        |-- libc.so\n"
+               "        |-- libc.so.6 -> libc-2.15.90.so\n"
+               "        |-- libdl-2.15.90.so\n"
+               "        |-- libdl.so -> libdl-2.15.90.so\n"
+               "        |-- libdl.so.2 -> libdl-2.15.90.so\n"
+               "        |-- libtinfo.so.5 -> libtinfo.so.5.9\n"
+               "        `-- libtinfo.so.5.9\n"
+               , program_invocation_short_name, program_invocation_short_name, program_invocation_short_name);
         exit(status);
 }
 
@@ -595,7 +604,7 @@ static int parse_argv(int argc, char *argv[])
                 ARG_DEBUG
         };
 
-        static const struct option const options[] = {
+        static struct option const options[] = {
                 {"help", no_argument, NULL, 'h'},
                 {"version", no_argument, NULL, ARG_VERSION},
                 {"dir", no_argument, NULL, 'd'},
@@ -691,7 +700,7 @@ static int resolve_lazy(int argc, char **argv)
 
 static char *find_binary(const char *src)
 {
-        char *path;
+        _cleanup_free_ char *path = NULL;
         char *p, *q;
         bool end = false;
         char *newsrc = NULL;
@@ -703,6 +712,12 @@ static char *find_binary(const char *src)
         }
         path = strdup(path);
         p = path;
+
+        if (path == NULL) {
+                log_error("Out of memory!");
+                exit(EXIT_FAILURE);
+        }
+
         log_debug("PATH=%s", path);
 
         do {
@@ -716,6 +731,11 @@ static char *find_binary(const char *src)
                         *q = '\0';
 
                 asprintf(&newsrc, "%s/%s", p, src);
+                if (newsrc == NULL) {
+                        log_error("Out of memory!");
+                        exit(EXIT_FAILURE);
+                }
+
                 p = q + 1;
 
                 if (stat(newsrc, &sb) != 0) {
@@ -729,9 +749,9 @@ static char *find_binary(const char *src)
 
         } while (!end);
 
-        free(path);
         if (newsrc)
                 log_debug("find_binary(%s) == %s", src, newsrc);
+
         return newsrc;
 }
 
@@ -773,22 +793,20 @@ static int install_all(int argc, char **argv)
                 log_debug("Handle '%s'", argv[i]);
 
                 if (strchr(argv[i], '/') == NULL) {
-                        char *newsrc = find_binary(argv[i]);
+                        _cleanup_free_ char *newsrc = find_binary(argv[i]);
                         if (newsrc) {
                                 log_debug("dracut_install '%s'", newsrc);
                                 ret = dracut_install(newsrc, newsrc, arg_createdir, arg_resolvedeps, true);
                                 if (ret == 0) {
                                         log_debug("dracut_install '%s' OK", newsrc);
                                 }
-                                free(newsrc);
                         } else {
                                 ret = -1;
                         }
 
                 } else {
-                        char *dest = strdup(argv[i]);
+                        _cleanup_free_ char *dest = strdup(argv[i]);
                         ret = dracut_install(argv[i], dest, arg_createdir, arg_resolvedeps, true);
-                        free(dest);
                 }
 
                 if ((ret != 0) && (!arg_optional)) {
diff --git a/install/macro.h b/install/macro.h
index 1c0aa91..ac61b49 100644
--- a/install/macro.h
+++ b/install/macro.h
@@ -1,7 +1,6 @@
 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
-#ifndef foomacrohfoo
-#define foomacrohfoo
+#pragma once
 
 /***
   This file is part of systemd.
@@ -45,16 +44,38 @@
 #define _hidden_ __attribute__ ((visibility("hidden")))
 #define _weakref_(x) __attribute__((weakref(#x)))
 #define _introspect_(x) __attribute__((section("introspect." x)))
+#define _alignas_(x) __attribute__((aligned(__alignof(x))))
+#define _cleanup_(x) __attribute__((cleanup(x)))
+
+/* automake test harness */
+#define EXIT_TEST_SKIP 77
 
 #define XSTRINGIFY(x) #x
 #define STRINGIFY(x) XSTRINGIFY(x)
 
 /* Rounds up */
-#define ALIGN(l) ALIGN_TO((l), sizeof(void*))
+
+#define ALIGN4(l) (((l) + 3) & ~3)
+#define ALIGN8(l) (((l) + 7) & ~7)
+
+#if __SIZEOF_POINTER__ == 8
+#define ALIGN(l) ALIGN8(l)
+#elif __SIZEOF_POINTER__ == 4
+#define ALIGN(l) ALIGN4(l)
+#else
+#error "Wut? Pointers are neither 4 nor 8 bytes long?"
+#endif
+
+#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) p))
+#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) p))
+#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) p))
+
 static inline size_t ALIGN_TO(size_t l, size_t ali) {
         return ((l + ali - 1) & ~(ali - 1));
 }
 
+#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) p))
+
 #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
 
 /*
@@ -64,34 +85,35 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
  * @member: the name of the member within the struct.
  *
  */
-#define container_of(ptr, type, member) ({ \
-        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
-        (type *)( (char *)__mptr - offsetof(type,member) );})
+#define container_of(ptr, type, member)                                 \
+        __extension__ ({                                                \
+                        const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+                        (type *)( (char *)__mptr - offsetof(type,member) ); \
+                })
 
-#ifndef MAX
-#define MAX(a,b)                                \
-        __extension__ ({                        \
-                        typeof(a) _a = (a);     \
-                        typeof(b) _b = (b);     \
-                        _a > _b ? _a : _b;      \
+#undef MAX
+#define MAX(a,b)                                 \
+        __extension__ ({                         \
+                        typeof(a) _a = (a);      \
+                        typeof(b) _b = (b);      \
+                        _a > _b ? _a : _b;       \
                 })
-#endif
 
-#define MAX3(a,b,c)                             \
-        MAX(MAX(a,b),c)
+#define MAX3(x,y,z)                              \
+        __extension__ ({                         \
+                        typeof(x) _c = MAX(x,y); \
+                        MAX(_c, z);              \
+                })
 
-#ifndef MIN
+#undef MIN
 #define MIN(a,b)                                \
         __extension__ ({                        \
                         typeof(a) _a = (a);     \
                         typeof(b) _b = (b);     \
                         _a < _b ? _a : _b;      \
                 })
-#endif
-
-#define MIN3(a,b,c)                             \
-        MIN(MIN(a,b),c)
 
+#ifndef CLAMP
 #define CLAMP(x, low, high)                                             \
         __extension__ ({                                                \
                         typeof(x) _x = (x);                             \
@@ -99,6 +121,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
                         typeof(high) _high = (high);                    \
                         ((_x > _high) ? _high : ((_x < _low) ? _low : _x)); \
                 })
+#endif
 
 #define assert_se(expr)                                                 \
         do {                                                            \
@@ -119,14 +142,21 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
                 log_assert_failed_unreachable(t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
         } while (false)
 
-#define assert_cc(expr)                            \
-        do {                                       \
-                switch (0) {                       \
-                        case 0:                    \
-                        case !!(expr):             \
-                                ;                  \
-                }                                  \
+#if defined(static_assert)
+#define assert_cc(expr)                         \
+        do {                                    \
+                static_assert(expr, #expr);     \
+        } while (false)
+#else
+#define assert_cc(expr)                         \
+        do {                                    \
+                switch (0) {                    \
+                case 0:                         \
+                case !!(expr):                  \
+                        ;                       \
+                }                               \
         } while (false)
+#endif
 
 #define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
 #define UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
@@ -149,6 +179,8 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
 #define memzero(x,l) (memset((x), 0, (l)))
 #define zero(x) (memzero(&(x), sizeof(x)))
 
+#define CHAR_TO_STR(x) ((char[2]) { x, 0 })
+
 #define char_array_0(x) x[sizeof(x)-1] = 0;
 
 #define IOVEC_SET_STRING(i, s)                  \
@@ -187,6 +219,66 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
         return k;
 }
 
-#include "log.h"
+#define VA_FORMAT_ADVANCE(format, ap)                                   \
+do {                                                                    \
+        int _argtypes[128];                                             \
+        size_t _i, _k;                                                  \
+        _k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
+        assert(_k < ELEMENTSOF(_argtypes));                             \
+        for (_i = 0; _i < _k; _i++) {                                   \
+                if (_argtypes[_i] & PA_FLAG_PTR)  {                     \
+                        (void) va_arg(ap, void*);                       \
+                        continue;                                       \
+                }                                                       \
+                                                                        \
+                switch (_argtypes[_i]) {                                \
+                case PA_INT:                                            \
+                case PA_INT|PA_FLAG_SHORT:                              \
+                case PA_CHAR:                                           \
+                        (void) va_arg(ap, int);                         \
+                        break;                                          \
+                case PA_INT|PA_FLAG_LONG:                               \
+                        (void) va_arg(ap, long int);                    \
+                        break;                                          \
+                case PA_INT|PA_FLAG_LONG_LONG:                          \
+                        (void) va_arg(ap, long long int);               \
+                        break;                                          \
+                case PA_WCHAR:                                          \
+                        (void) va_arg(ap, wchar_t);                     \
+                        break;                                          \
+                case PA_WSTRING:                                        \
+                case PA_STRING:                                         \
+                case PA_POINTER:                                        \
+                        (void) va_arg(ap, void*);                       \
+                        break;                                          \
+                case PA_FLOAT:                                          \
+                case PA_DOUBLE:                                         \
+                        (void) va_arg(ap, double);                      \
+                        break;                                          \
+                case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:                     \
+                        (void) va_arg(ap, long double);                 \
+                        break;                                          \
+                default:                                                \
+                        assert_not_reached("Unknown format string argument."); \
+                }                                                       \
+        }                                                               \
+} while(false)
+
+ /* Because statfs.t_type can be int on some architecures, we have to cast
+  * the const magic to the type, otherwise the compiler warns about
+  * signed/unsigned comparison, because the magic can be 32 bit unsigned.
+ */
+#define F_TYPE_CMP(a, b) (a == (typeof(a)) b)
 
-#endif
+
+/* Returns the number of chars needed to format variables of the
+ * specified type as a decimal string. Adds in extra space for a
+ * negative '-' prefix. */
+
+#define DECIMAL_STR_MAX(type)                                           \
+        (1+(sizeof(type) <= 1 ? 3 :                                     \
+            sizeof(type) <= 2 ? 5 :                                     \
+            sizeof(type) <= 4 ? 10 :                                    \
+            sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
+
+#include "log.h"
diff --git a/install/util.h b/install/util.h
index 9085935..e86b2f2 100644
--- a/install/util.h
+++ b/install/util.h
@@ -507,6 +507,42 @@ void* memdup(const void *p, size_t l);
 
 int is_kernel_thread(pid_t pid);
 
+static inline void freep(void *p) {
+        free(*(void**) p);
+}
+
+static inline void fclosep(FILE **f) {
+        if (*f)
+                fclose(*f);
+}
+
+static inline void pclosep(FILE **f) {
+        if (*f)
+                pclose(*f);
+}
+
+static inline void closep(int *fd) {
+        if (*fd >= 0)
+                close_nointr_nofail(*fd);
+}
+
+static inline void closedirp(DIR **d) {
+        if (*d)
+                closedir(*d);
+}
+
+static inline void umaskp(mode_t *u) {
+        umask(*u);
+}
+
+#define _cleanup_free_ _cleanup_(freep)
+#define _cleanup_fclose_ _cleanup_(fclosep)
+#define _cleanup_pclose_ _cleanup_(pclosep)
+#define _cleanup_close_ _cleanup_(closep)
+#define _cleanup_closedir_ _cleanup_(closedirp)
+#define _cleanup_umask_ _cleanup_(umaskp)
+#define _cleanup_globfree_ _cleanup_(globfree)
+
 int fd_inc_sndbuf(int fd, size_t n);
 int fd_inc_rcvbuf(int fd, size_t n);