about summary refs log tree commit diff
path: root/shared/systemd/src/basic/stat-util.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-06-28 18:58:14 +0200
committerMichael Biebl <biebl@debian.org>2020-06-28 18:58:14 +0200
commita54ac63bbf9b2c71026ac9028a8ffaf186cf3c82 (patch)
tree6a32883bd916c4096357b35298beff6db8bcd0b5 /shared/systemd/src/basic/stat-util.c
parent45e8e1149027529194982212c804c0468aa01d98 (diff)
New upstream version 1.25.90 upstream/1.25.90
Diffstat (limited to 'shared/systemd/src/basic/stat-util.c')
-rw-r--r--shared/systemd/src/basic/stat-util.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/shared/systemd/src/basic/stat-util.c b/shared/systemd/src/basic/stat-util.c
index a895c1c3..5c51e13a 100644
--- a/shared/systemd/src/basic/stat-util.c
+++ b/shared/systemd/src/basic/stat-util.c
@@ -99,10 +99,10 @@ bool null_or_empty(struct stat *st) {
         if (S_ISREG(st->st_mode) && st->st_size <= 0)
                 return true;
 
-        /* We don't want to hardcode the major/minor of /dev/null,
-         * hence we do a simpler "is this a device node?" check. */
+        /* We don't want to hardcode the major/minor of /dev/null, hence we do a simpler "is this a character
+         * device node?" check. */
 
-        if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
+        if (S_ISCHR(st->st_mode))
                 return true;
 
         return false;
@@ -113,6 +113,10 @@ int null_or_empty_path(const char *fn) {
 
         assert(fn);
 
+        /* If we have the path, let's do an easy text comparison first. */
+        if (path_equal(fn, "/dev/null"))
+                return true;
+
         if (stat(fn, &st) < 0)
                 return -errno;
 
@@ -183,13 +187,12 @@ int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
 }
 
 int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
-        _cleanup_close_ int fd = -1;
+        struct statfs s;
 
-        fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
-        if (fd < 0)
+        if (statfs(path, &s) < 0)
                 return -errno;
 
-        return fd_is_fs_type(fd, magic_value);
+        return is_fs_type(&s, magic_value);
 }
 
 bool is_temporary_fs(const struct statfs *s) {
@@ -384,4 +387,37 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret
 
         return 0;
 }
+
+int proc_mounted(void) {
+        int r;
+
+        /* A quick check of procfs is properly mounted */
+
+        r = path_is_fs_type("/proc/", PROC_SUPER_MAGIC);
+        if (r == -ENOENT) /* not mounted at all */
+                return false;
+
+        return r;
+}
+
+bool stat_inode_unmodified(const struct stat *a, const struct stat *b) {
+
+        /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to
+         * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file
+         * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file
+         * size, backing device, inode type and if this refers to a device not the major/minor.
+         *
+         * Note that we don't care if file attributes such as ownership or access mode change, this here is
+         * about contents of the file. The purpose here is to detect file contents changes, and nothing
+         * else. */
+
+        return a && b &&
+                (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */
+                ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 &&  /* same inode type */
+                a->st_mtime == b->st_mtime &&
+                (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */
+                a->st_dev == b->st_dev &&
+                a->st_ino == b->st_ino &&
+                (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */
+}
 #endif /* NM_IGNORED */