From: Lennart Poettering Date: Mon, 14 Feb 2011 20:55:06 +0000 (+0100) Subject: tmpfiles: never delete AF_UNIX sockets that are alive X-Git-Tag: v18~21 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=17b9052533551fc786f73f1a2898ac6a28fe1210 tmpfiles: never delete AF_UNIX sockets that are alive --- diff --git a/src/tmpfiles.c b/src/tmpfiles.c index 9b697e47e..01668da87 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;