X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbasic%2Fpath-util.c;h=369a2b2a07d6fa113fc6f5aca403845b40c610f1;hb=98882279e46c4a4776d68872340f636bd1ec1863;hp=3ebc5c5366c4c3e70f786218b54a4143dc8351f1;hpb=eaca07ccfdf5d7dabc50afc7e539c2413dd69d3e;p=elogind.git diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 3ebc5c536..369a2b2a0 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -20,11 +18,11 @@ ***/ #include -#include +#include #include #include #include -#include +#include #include /* When we include libgen.h because we need dirname() we immediately @@ -34,18 +32,16 @@ #undef basename #include "alloc-util.h" -#include "fd-util.h" -#include "fileio.h" +#include "extract-word.h" #include "fs-util.h" #include "log.h" #include "macro.h" #include "missing.h" -#include "parse-util.h" #include "path-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" -#include "util.h" +#include "time-util.h" bool path_is_absolute(const char *p) { return p[0] == '/'; @@ -55,8 +51,7 @@ bool is_path(const char *p) { return !!strchr(p, '/'); } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int path_split_and_make_absolute(const char *p, char ***ret) { char **l; int r; @@ -77,7 +72,6 @@ int path_split_and_make_absolute(const char *p, char ***ret) { *ret = l; return r; } -#endif // 0 char *path_make_absolute(const char *p, const char *prefix) { assert(p); @@ -90,6 +84,7 @@ char *path_make_absolute(const char *p, const char *prefix) { return strjoin(prefix, "/", p, NULL); } +#endif // 0 int path_make_absolute_cwd(const char *p, char **ret) { char *c; @@ -105,9 +100,9 @@ int path_make_absolute_cwd(const char *p, char **ret) { else { _cleanup_free_ char *cwd = NULL; - cwd = get_current_dir_name(); - if (!cwd) - return -errno; + cwd = get_current_dir_name(); + if (!cwd) + return negative_errno(); c = strjoin(cwd, "/", p, NULL); } @@ -118,8 +113,7 @@ int path_make_absolute_cwd(const char *p, char **ret) { return 0; } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int path_make_relative(const char *from_dir, const char *to_path, char **_r) { char *r, *p; unsigned n_parents; @@ -447,8 +441,7 @@ bool path_equal_or_files_same(const char *a, const char *b) { return path_equal(a, b) || files_same(a, b) > 0; } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind char* path_join(const char *root, const char *path, const char *rest) { assert(path); @@ -464,9 +457,6 @@ char* path_join(const char *root, const char *path, const char *rest) { rest && rest[0] == '/' ? rest+1 : rest, NULL); } -#endif // 0 -/// UNNEEDED by elogind -#if 0 int find_binary(const char *name, char **ret) { int last_error, r; @@ -487,10 +477,10 @@ int find_binary(const char *name, char **ret) { return 0; } - /** - * Plain getenv, not secure_getenv, because we want - * to actually allow the user to pick the binary. - */ + /** + * Plain getenv, not secure_getenv, because we want + * to actually allow the user to pick the binary. + */ p = getenv("PATH"); if (!p) p = DEFAULT_PATH; @@ -507,7 +497,7 @@ int find_binary(const char *name, char **ret) { break; if (!path_is_absolute(element)) - continue; + continue; j = strjoin(element, "/", name, NULL); if (!j) @@ -584,10 +574,10 @@ static int binary_is_good(const char *binary) { if (r < 0) return r; - return !path_equal(d, "true") && - !path_equal(d, "/bin/true") && - !path_equal(d, "/usr/bin/true") && - !path_equal(d, "/dev/null"); + return !PATH_IN_SET(d, "true" + "/bin/true", + "/usr/bin/true", + "/dev/null"); } int fsck_exists(const char *fstype) { @@ -647,7 +637,6 @@ char *prefix_root(const char *root, const char *path) { strcpy(p, path); return n; } -#endif // 0 int parse_path_argument_and_warn(const char *path, bool suppress_root, char **arg) { char *p; @@ -680,6 +669,7 @@ int parse_path_argument_and_warn(const char *path, bool suppress_root, char **ar *arg = p; return 0; } +#endif // 0 char* dirname_malloc(const char *path) { char *d, *dir, *dir2; @@ -772,36 +762,56 @@ char *file_in_same_dir(const char *path, const char *filename) { return ret; } -bool hidden_file_allow_backup(const char *filename) { - assert(filename); - - return - filename[0] == '.' || - streq(filename, "lost+found") || - streq(filename, "aquota.user") || - streq(filename, "aquota.group") || - endswith(filename, ".rpmnew") || - endswith(filename, ".rpmsave") || - endswith(filename, ".rpmorig") || - endswith(filename, ".dpkg-old") || - endswith(filename, ".dpkg-new") || - endswith(filename, ".dpkg-tmp") || - endswith(filename, ".dpkg-dist") || - endswith(filename, ".dpkg-bak") || - endswith(filename, ".dpkg-backup") || - endswith(filename, ".dpkg-remove") || - endswith(filename, ".swp"); -} +bool hidden_or_backup_file(const char *filename) { + const char *p; -bool hidden_file(const char *filename) { assert(filename); - if (endswith(filename, "~")) + if (filename[0] == '.' || + streq(filename, "lost+found") || + streq(filename, "aquota.user") || + streq(filename, "aquota.group") || + endswith(filename, "~")) return true; - return hidden_file_allow_backup(filename); + p = strrchr(filename, '.'); + if (!p) + return false; + + /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up + * with always new suffixes and that everybody else should just adjust to that, then it really should be on + * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt + * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional + * string. Specifically: there's now: + * + * The generic suffixes "~" and ".bak" for backup files + * The generic prefix "." for hidden files + * + * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist" + * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead. + */ + + return STR_IN_SET(p + 1, + "rpmnew", + "rpmsave", + "rpmorig", + "dpkg-old", + "dpkg-new", + "dpkg-tmp", + "dpkg-dist", + "dpkg-bak", + "dpkg-backup", + "dpkg-remove", + "ucf-new", + "ucf-old", + "ucf-dist", + "swp", + "bak", + "old", + "new"); } +#if 0 /// UNNEEDED by elogind bool is_device_path(const char *path) { /* Returns true on paths that refer to a device, either in @@ -811,3 +821,70 @@ bool is_device_path(const char *path) { path_startswith(path, "/dev/") || path_startswith(path, "/sys/"); } +#endif // 0 + +int systemd_installation_has_version(const char *root, unsigned minimal_version) { + const char *pattern; + int r; + + /* Try to guess if systemd installation is later than the specified version. This + * is hacky and likely to yield false negatives, particularly if the installation + * is non-standard. False positives should be relatively rare. + */ + + NULSTR_FOREACH(pattern, + /* /lib works for systems without usr-merge, and for systems with a sane + * usr-merge, where /lib is a symlink to /usr/lib. /usr/lib is necessary + * for Gentoo which does a merge without making /lib a symlink. + */ + "lib/systemd/libsystemd-shared-*.so\0" + "usr/lib/systemd/libsystemd-shared-*.so\0") { + + _cleanup_strv_free_ char **names = NULL; + _cleanup_free_ char *path = NULL; + char *c, **name; + + path = prefix_root(root, pattern); + if (!path) + return -ENOMEM; + + r = glob_extend(&names, path); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + + assert_se((c = endswith(path, "*.so"))); + *c = '\0'; /* truncate the glob part */ + + STRV_FOREACH(name, names) { + /* This is most likely to run only once, hence let's not optimize anything. */ + char *t, *t2; + unsigned version; + + t = startswith(*name, path); + if (!t) + continue; + + t2 = endswith(t, ".so"); + if (!t2) + continue; + + t2[0] = '\0'; /* truncate the suffix */ + + r = safe_atou(t, &version); + if (r < 0) { + log_debug_errno(r, "Found libsystemd shared at \"%s.so\", but failed to parse version: %m", *name); + continue; + } + + log_debug("Found libsystemd shared at \"%s.so\", version %u (%s).", + *name, version, + version >= minimal_version ? "OK" : "too old"); + if (version >= minimal_version) + return true; + } + } + + return false; +}