]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc_create: prepend pretty header to config file (v2)
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Fri, 12 Jul 2013 19:07:23 +0000 (14:07 -0500)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Mon, 15 Jul 2013 21:34:00 +0000 (16:34 -0500)
Define a sha1sum_file() function in utils.c.  Use that in lxcapi_create
to write out the sha1sum of the template being used.  If libgnutls is
not found, then the template sha1sum simply won't be printed into the
container config.

This patch also trivially fixes some cases where SYSERROR is used after
a fclose (masking errno) and missing consts in mkdir_p.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
configure.ac
src/lxc/lxccontainer.c
src/lxc/utils.c
src/lxc/utils.h

index 456700185788ac6478010a5d5c0061b2c81fff93..56638d4ee2d2f9a0349a3eab28ee596bc73ec95b 100644 (file)
@@ -105,6 +105,8 @@ if test "$enable_apparmor" = "check" ; then
 fi
 AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"])
 
+AC_CHECK_LIB([gnutls], [gnutls_hash_fast])
+
 AM_COND_IF([ENABLE_APPARMOR],
        [AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
        AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
index 446827c0a45b83fbfa6cbfb1f0a56c8631da2a69..0c13e06823331c0101ff5a4bad639cbb86288ed8 100644 (file)
@@ -870,6 +870,107 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
        return true;
 }
 
+bool prepend_lxc_header(char *path, const char *t, char *const argv[])
+{
+       size_t flen;
+       char *contents, *tpath;
+       int i, ret;
+       FILE *f;
+       unsigned char md_value[SHA_DIGEST_LENGTH];
+       bool have_tpath = false;
+
+       if ((f = fopen(path, "r")) == NULL) {
+               SYSERROR("Opening old config");
+               return false;
+       }
+       if (fseek(f, 0, SEEK_END) < 0) {
+               SYSERROR("Seeking to end of old config file");
+               fclose(f);
+               return false;
+       }
+       if ((flen = ftell(f)) < 0) {
+               SYSERROR("telling size of old config");
+               fclose(f);
+               return false;
+       }
+       if (fseek(f, 0, SEEK_SET) < 0) {
+               SYSERROR("rewinding old config");
+               fclose(f);
+               return false;
+       }
+       if ((contents = malloc(flen + 1)) == NULL) {
+               SYSERROR("out of memory");
+               fclose(f);
+               return false;
+       }
+       if (fread(contents, 1, flen, f) != flen) {
+               SYSERROR("Reading old config");
+               free(contents);
+               fclose(f);
+               return false;
+       }
+       contents[flen] = '\0';
+       if (fclose(f) < 0) {
+               SYSERROR("closing old config");
+               free(contents);
+               return false;
+       }
+
+       if ((tpath = get_template_path(t)) < 0) {
+               ERROR("bad template: %s\n", t);
+               free(contents);
+               return false;
+       }
+
+#if HAVE_LIBGNUTLS
+       if (tpath) {
+               have_tpath = true;
+               ret = sha1sum_file(tpath, md_value);
+               if (ret < 0) {
+                       ERROR("Error getting sha1sum of %s", tpath);
+                       free(contents);
+                       return false;
+               }
+               free(tpath);
+       }
+#endif
+
+       if ((f = fopen(path, "w")) == NULL) {
+               SYSERROR("reopening config for writing");
+               free(contents);
+               return false;
+       }
+       fprintf(f, "# Template used to create this container: %s\n", t);
+       if (argv) {
+               fprintf(f, "# Parameters passed to the template:");
+               while (*argv) {
+                       fprintf(f, " %s", *argv);
+                       argv++;
+               }
+               fprintf(f, "\n");
+       }
+#if HAVE_LIBGNUTLS
+       if (have_tpath) {
+               fprintf(f, "# Template script checksum (SHA-1): ");
+               for (i=0; i<SHA_DIGEST_LENGTH; i++)
+                       fprintf(f, "%02x", md_value[i]);
+               fprintf(f, "\n");
+       }
+#endif
+       if (fwrite(contents, 1, flen, f) != flen) {
+               SYSERROR("Writing original contents");
+               free(contents);
+               fclose(f);
+               return false;
+       }
+       free(contents);
+       if (fclose(f) < 0) {
+               SYSERROR("Closing config file after write");
+               return false;
+       }
+       return true;
+}
+
 static bool lxcapi_destroy(struct lxc_container *c);
 /*
  * lxcapi_create:
@@ -967,6 +1068,11 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
        if (c->lxc_conf)
                lxc_conf_free(c->lxc_conf);
        c->lxc_conf = NULL;
+
+       if (!prepend_lxc_header(c->configfile, tpath, argv)) {
+               ERROR("Error prepending header to configuration file");
+               goto out_unlock;
+       }
        bret = load_config_locked(c, c->configfile);
 
 out_unlock:
@@ -1623,13 +1729,13 @@ static int update_name_and_paths(const char *path, struct lxc_container *oldc,
        }
        flen = ftell(f);
        if (flen < 0) {
-               fclose(f);
                SYSERROR("telling size of old config");
+               fclose(f);
                return -1;
        }
        if (fseek(f, 0, SEEK_SET) < 0) {
-               fclose(f);
                SYSERROR("rewinding old config");
+               fclose(f);
                return -1;
        }
        contents = malloc(flen+1);
@@ -1639,15 +1745,15 @@ static int update_name_and_paths(const char *path, struct lxc_container *oldc,
                return -1;
        }
        if (fread(contents, 1, flen, f) != flen) {
+               SYSERROR("reading old config");
                free(contents);
                fclose(f);
-               SYSERROR("reading old config");
                return -1;
        }
        contents[flen] = '\0';
        if (fclose(f) < 0) {
-               free(contents);
                SYSERROR("closing old config");
+               free(contents);
                return -1;
        }
 
index 136f943a1592b2df9a629322a36b88bc75d32589..c3f734b050f2dbd0f88033ea0a4276e584308ec3 100644 (file)
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include "utils.h"
 #include "log.h"
 
 lxc_log_define(lxc_utils, lxc);
@@ -173,10 +174,10 @@ extern int get_u16(unsigned short *val, const char *arg, int base)
        return 0;
 }
 
-extern int mkdir_p(char *dir, mode_t mode)
+extern int mkdir_p(const char *dir, mode_t mode)
 {
-       char *tmp = dir;
-       char *orig = dir;
+       const char *tmp = dir;
+       const char *orig = dir;
        char *makeme;
 
        do {
@@ -392,3 +393,57 @@ int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected
        }
        return ret;
 }
+
+#if HAVE_LIBGNUTLS
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+int sha1sum_file(char *fnam, unsigned char *digest)
+{
+       char *buf;
+       int ret;
+       FILE *f;
+       long flen;
+
+       if (!fnam)
+               return -1;
+       if ((f = fopen(fnam, "r")) < 0) {
+               SYSERROR("Error opening template");
+               return -1;
+       }
+       if (fseek(f, 0, SEEK_END) < 0) {
+               SYSERROR("Error seeking to end of template");
+               fclose(f);
+               return -1;
+       }
+       if ((flen = ftell(f)) < 0) {
+               SYSERROR("Error telling size of template");
+               fclose(f);
+               return -1;
+       }
+       if (fseek(f, 0, SEEK_SET) < 0) {
+               SYSERROR("Error seeking to start of template");
+               fclose(f);
+               return -1;
+       }
+       if ((buf = malloc(flen+1)) == NULL) {
+               SYSERROR("Out of memory");
+               fclose(f);
+               return -1;
+       }
+       if (fread(buf, 1, flen, f) != flen) {
+               SYSERROR("Failure reading template");
+               free(buf);
+               fclose(f);
+               return -1;
+       }
+       if (fclose(f) < 0) {
+               SYSERROR("Failre closing template");
+               free(buf);
+               return -1;
+       }
+       buf[flen] = '\0';
+       ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
+       free(buf);
+       return ret;
+}
+#endif
index 063f76cce3dd29e251a98f926bb639f9d6b2b997..14b8439d412e267231694eb3834b342e40a89fcc 100644 (file)
@@ -176,5 +176,9 @@ extern int lxc_wait_for_pid_status(pid_t pid);
 extern int lxc_write_nointr(int fd, const void* buf, size_t count);
 extern int lxc_read_nointr(int fd, void* buf, size_t count);
 extern int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf);
+#if HAVE_LIBGNUTLS
+#define SHA_DIGEST_LENGTH 20
+extern int sha1sum_file(char *fnam, unsigned char *md_value);
+#endif
 
 #endif