diff options
author | Lennart Poettering <lennart@poettering.net> | 2011-02-14 21:55:06 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2011-02-14 21:55:06 +0100 |
commit | 17b9052533551fc786f73f1a2898ac6a28fe1210 (patch) | |
tree | 3597fe96ef82cffc0c1b220d271af3ff05f5f1b7 /src/tmpfiles.c | |
parent | 6a3b1508f7a9c8ecf712beb44baa13f252f0d3d8 (diff) |
tmpfiles: never delete AF_UNIX sockets that are alive
Diffstat (limited to 'src/tmpfiles.c')
-rw-r--r-- | src/tmpfiles.c | 84 |
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; |