chiark / gitweb /
nspawn: skip symlink to a combined cgroup hierarchy if it already exists
[elogind.git] / src / shared / util.c
index e36389eaceac7c10fabf1ab44bab051c8178deed..9b67dd8296fde6fab7ae3b862bf7ce63fc21e015 100644 (file)
@@ -2766,6 +2766,28 @@ int symlink_atomic(const char *from, const char *to) {
         return 0;
 }
 
+int symlink_idempotent(const char *from, const char *to) {
+        _cleanup_free_ char *p = NULL;
+        int r;
+
+        assert(from);
+        assert(to);
+
+        if (symlink(from, to) < 0) {
+                if (errno != EEXIST)
+                        return -errno;
+
+                r = readlink_malloc(to, &p);
+                if (r < 0)
+                        return r;
+
+                if (!streq(p, from))
+                        return -EINVAL;
+        }
+
+        return 0;
+}
+
 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
         _cleanup_free_ char *t = NULL;
         int r;
@@ -4839,7 +4861,7 @@ int open_tmpfile(const char *path, int flags) {
 
 #ifdef O_TMPFILE
         /* Try O_TMPFILE first, if it is supported */
-        fd = open(path, flags|O_TMPFILE, S_IRUSR|S_IWUSR);
+        fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR);
         if (fd >= 0)
                 return fd;
 #endif
@@ -5683,6 +5705,9 @@ int free_and_strdup(char **p, const char *s) {
         /* Replaces a string pointer with an strdup()ed new string,
          * possibly freeing the old one. */
 
+        if (streq_ptr(*p, s))
+                return 0;
+
         if (s) {
                 t = strdup(s);
                 if (!t)
@@ -5693,7 +5718,7 @@ int free_and_strdup(char **p, const char *s) {
         free(*p);
         *p = t;
 
-        return 0;
+        return 1;
 }
 
 int sethostname_idempotent(const char *s) {