summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2011-02-14 21:55:06 +0100
committerLennart Poettering <lennart@poettering.net>2011-02-14 21:55:06 +0100
commit17b9052533551fc786f73f1a2898ac6a28fe1210 (patch)
tree3597fe96ef82cffc0c1b220d271af3ff05f5f1b7
parent6a3b1508f7a9c8ecf712beb44baa13f252f0d3d8 (diff)
tmpfiles: never delete AF_UNIX sockets that are alive
-rw-r--r--src/tmpfiles.c84
1 files changed, 83 insertions, 1 deletions
diff --git a/src/tmpfiles.c b/src/tmpfiles.c
index 9b697e47e8..01668da87e 100644
--- a/src/tmpfiles.c
+++ b/src/tmpfiles.c
@@ -80,6 +80,7 @@ typedef struct Item {
} Item;
static Hashmap *items = NULL, *globs = NULL;
+static Set *unix_sockets = NULL;
static bool arg_create = false;
static bool arg_clean = false;
@@ -104,6 +105,78 @@ static struct Item* find_glob(Hashmap *h, const char *match) {
return NULL;
}
+static void load_unix_sockets(void) {
+ FILE *f = NULL;
+ char line[LINE_MAX];
+
+ if (unix_sockets)
+ return;
+
+ /* We maintain a cache of the sockets we found in
+ * /proc/net/unix to speed things up a little. */
+
+ if (!(unix_sockets = set_new(string_hash_func, string_compare_func)))
+ return;
+
+ if (!(f = fopen("/proc/net/unix", "re")))
+ return;
+
+ if (!(fgets(line, sizeof(line), f)))
+ goto fail;
+
+ for (;;) {
+ char *p, *s;
+ int k;
+
+ if (!(fgets(line, sizeof(line), f)))
+ break;
+
+ truncate_nl(line);
+
+ if (strlen(line) < 53)
+ continue;
+
+ p = line + 53;
+ p += strspn(p, WHITESPACE);
+ p += strcspn(p, WHITESPACE);
+ p += strspn(p, WHITESPACE);
+
+ if (*p != '/')
+ continue;
+
+ if (!(s = strdup(p)))
+ goto fail;
+
+ if ((k = set_put(unix_sockets, s)) < 0) {
+ free(s);
+
+ if (k != -EEXIST)
+ goto fail;
+ }
+ }
+
+ return;
+
+fail:
+ set_free_free(unix_sockets);
+ unix_sockets = NULL;
+
+ if (f)
+ fclose(f);
+}
+
+static bool unix_socket_alive(const char *fn) {
+ assert(fn);
+
+ load_unix_sockets();
+
+ if (unix_sockets)
+ return !!set_get(unix_sockets, (char*) fn);
+
+ /* We don't know, so assume yes */
+ return true;
+}
+
static int dir_cleanup(
const char *p,
DIR *d,
@@ -214,7 +287,7 @@ static int dir_cleanup(
if (s.st_mode & S_ISVTX)
continue;
- if (mountpoint) {
+ if (mountpoint && S_ISREG(s.st_mode)) {
if (streq(dent->d_name, ".journal") &&
s.st_uid == 0)
continue;
@@ -224,6 +297,10 @@ static int dir_cleanup(
continue;
}
+ /* Ignore sockets that are listed in /proc/net/unix */
+ if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path))
+ continue;
+
age = MAX3(timespec_load(&s.st_mtim),
timespec_load(&s.st_atim),
timespec_load(&s.st_ctim));
@@ -901,9 +978,14 @@ finish:
while ((i = hashmap_steal_first(items)))
item_free(i);
+ while ((i = hashmap_steal_first(globs)))
+ item_free(i);
+
hashmap_free(items);
hashmap_free(globs);
+ set_free_free(unix_sockets);
+
label_finish();
return r;