diff --git a/src/basic/path-util.c b/src/basic/path-util.c index b972396249..f832f85c68 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -485,10 +485,6 @@ int path_compare(const char *a, const char *b) { } } -bool path_equal_or_inode_same(const char *a, const char *b, int flags) { - return path_equal(a, b) || inode_same(a, b, flags) > 0; -} - int path_compare_filename(const char *a, const char *b) { _cleanup_free_ char *fa = NULL, *fb = NULL; int r, j, k; diff --git a/src/basic/path-util.h b/src/basic/path-util.h index af7f229908..97175bee11 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -6,6 +6,7 @@ #include #include "macro.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -77,7 +78,9 @@ static inline bool path_equal_filename(const char *a, const char *b) { return path_compare_filename(a, b) == 0; } -bool path_equal_or_inode_same(const char *a, const char *b, int flags); +static inline bool path_equal_or_inode_same(const char *a, const char *b, int flags) { + return path_equal(a, b) || inode_same(a, b, flags) > 0; +} char* path_extend_internal(char **x, ...); #define path_extend(x, ...) path_extend_internal(x, __VA_ARGS__, POINTER_MAX) diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c index b6d3d257ac..23c1a0a3c8 100644 --- a/src/hibernate-resume/hibernate-resume-generator.c +++ b/src/hibernate-resume/hibernate-resume-generator.c @@ -8,6 +8,7 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "device-nodes.h" #include "dropin.h" #include "efivars.h" #include "fd-util.h" @@ -170,9 +171,16 @@ static int parse_efi_hibernate_location(void) { arg_resume_device = TAKE_PTR(device); arg_resume_offset = location.offset; } else { - if (!path_equal_or_inode_same(arg_resume_device, device, 0)) - log_warning("resume=%s doesn't match with HibernateLocation device '%s', proceeding anyway with resume=.", - arg_resume_device, device); + if (!path_equal(arg_resume_device, device)) { + r = devnode_same(arg_resume_device, device); + if (r < 0) + log_debug_errno(r, + "Failed to check if resume=%s is the same device as HibernateLocation device '%s', ignoring: %m", + arg_resume_device, device); + if (r == 0) + log_warning("resume=%s doesn't match with HibernateLocation device '%s', proceeding anyway with resume=.", + arg_resume_device, device); + } if (arg_resume_offset != location.offset) log_warning("resume_offset=%" PRIu64 " doesn't match with HibernateLocation offset %" PRIu64 ", proceeding anyway with resume_offset=.", diff --git a/src/shared/device-nodes.c b/src/shared/device-nodes.c index bdbbb98c2c..d08c40fe2c 100644 --- a/src/shared/device-nodes.c +++ b/src/shared/device-nodes.c @@ -3,8 +3,10 @@ #include #include #include +#include #include "device-nodes.h" +#include "path-util.h" #include "string-util.h" #include "utf8.h" @@ -58,3 +60,28 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) { str_enc[j] = '\0'; return 0; } + +int devnode_same(const char *a, const char *b) { + struct stat sa, sb; + + assert(a); + assert(b); + + if (!valid_device_node_path(a) || !valid_device_node_path(b)) + return -EINVAL; + + if (stat(a, &sa) < 0) + return -errno; + if (stat(b, &sb) < 0) + return -errno; + + if (!S_ISBLK(sa.st_mode) && !S_ISCHR(sa.st_mode)) + return -ENODEV; + if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode)) + return -ENODEV; + + if (((sa.st_mode ^ sb.st_mode) & S_IFMT) != 0) /* both inode same device node type? */ + return false; + + return sa.st_rdev == sb.st_rdev; +} diff --git a/src/shared/device-nodes.h b/src/shared/device-nodes.h index a8b2564314..8b17a8e190 100644 --- a/src/shared/device-nodes.h +++ b/src/shared/device-nodes.h @@ -5,3 +5,5 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len); int allow_listed_char_for_devnode(char c, const char *additional); + +int devnode_same(const char *a, const char *b);