]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stat-util: generalize is_* and verify_* handling
authorMike Yuan <me@yhndnzj.com>
Sat, 2 Mar 2024 09:41:29 +0000 (17:41 +0800)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 4 Mar 2024 19:53:51 +0000 (19:53 +0000)
src/basic/mkdir.c
src/basic/stat-util.c
src/basic/stat-util.h
src/basic/time-util.c
src/firstboot/firstboot.c
src/kernel-install/kernel-install.c

index 5dd56c89a4ed8f08fdeb823ecb110ca793d4e060..7c1ad7dd64ad6b9096771b204260192729cf0caa 100644 (file)
@@ -112,7 +112,7 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui
 
         /* drop the last component */
         path = strndupa_safe(path, e - path);
-        r = is_dir_full(dir_fd, path, true);
+        r = is_dir_at(dir_fd, path, /* follow = */ true);
         if (r > 0)
                 return 0;
         if (r == 0)
index 6a8ec1ba2a79d329bc0827833dfda730026ae464..ec6273c7d0c53310d0c827e2376a2c21a07b18e3 100644 (file)
 #include "stat-util.h"
 #include "string-util.h"
 
-int is_symlink(const char *path) {
-        struct stat info;
+static int verify_stat_at(
+                int fd,
+                const char *path,
+                bool follow,
+                int (*verify_func)(const struct stat *st),
+                bool verify) {
 
-        assert(path);
+        struct stat st;
+        int r;
+
+        assert(fd >= 0 || fd == AT_FDCWD);
+        assert(!isempty(path) || !follow);
+        assert(verify_func);
 
-        if (lstat(path, &info) < 0)
+        if (fstatat(fd, strempty(path), &st,
+                    (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0)
                 return -errno;
 
-        return !!S_ISLNK(info.st_mode);
+        r = verify_func(&st);
+        return verify ? r : r >= 0;
 }
 
-int is_dir_full(int atfd, const char* path, bool follow) {
-        struct stat st;
-        int r;
+int stat_verify_regular(const struct stat *st) {
+        assert(st);
 
-        assert(atfd >= 0 || atfd == AT_FDCWD);
-        assert(atfd >= 0 || path);
+        /* Checks whether the specified stat() structure refers to a regular file. If not returns an
+         * appropriate error code. */
 
-        if (path)
-                r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW);
-        else
-                r = fstat(atfd, &st);
-        if (r < 0)
-                return -errno;
+        if (S_ISDIR(st->st_mode))
+                return -EISDIR;
+
+        if (S_ISLNK(st->st_mode))
+                return -ELOOP;
+
+        if (!S_ISREG(st->st_mode))
+                return -EBADFD;
 
-        return !!S_ISDIR(st.st_mode);
+        return 0;
 }
 
-int is_device_node(const char *path) {
-        struct stat info;
+int verify_regular_at(int fd, const char *path, bool follow) {
+        return verify_stat_at(fd, path, follow, stat_verify_regular, true);
+}
 
-        assert(path);
+int fd_verify_regular(int fd) {
+        assert(fd >= 0);
+        return verify_regular_at(fd, NULL, false);
+}
 
-        if (lstat(path, &info) < 0)
-                return -errno;
+int stat_verify_directory(const struct stat *st) {
+        assert(st);
 
-        return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
+        if (S_ISLNK(st->st_mode))
+                return -ELOOP;
+
+        if (!S_ISDIR(st->st_mode))
+                return -ENOTDIR;
+
+        return 0;
+}
+
+int fd_verify_directory(int fd) {
+        assert(fd >= 0);
+        return verify_stat_at(fd, NULL, false, stat_verify_directory, true);
+}
+
+int is_dir_at(int fd, const char *path, bool follow) {
+        return verify_stat_at(fd, path, follow, stat_verify_directory, false);
+}
+
+int is_dir(const char *path, bool follow) {
+        assert(!isempty(path));
+        return is_dir_at(AT_FDCWD, path, follow);
+}
+
+int stat_verify_symlink(const struct stat *st) {
+        assert(st);
+
+        if (S_ISDIR(st->st_mode))
+                return -EISDIR;
+
+        if (!S_ISLNK(st->st_mode))
+                return -ENOLINK;
+
+        return 0;
+}
+
+int is_symlink(const char *path) {
+        assert(!isempty(path));
+        return verify_stat_at(AT_FDCWD, path, false, stat_verify_symlink, false);
+}
+
+int stat_verify_linked(const struct stat *st) {
+        assert(st);
+
+        if (st->st_nlink <= 0)
+                return -EIDRM; /* recognizable error. */
+
+        return 0;
+}
+
+int fd_verify_linked(int fd) {
+        assert(fd >= 0);
+        return verify_stat_at(fd, NULL, false, stat_verify_linked, true);
+}
+
+int stat_verify_device_node(const struct stat *st) {
+        assert(st);
+
+        if (S_ISLNK(st->st_mode))
+                return -ELOOP;
+
+        if (S_ISDIR(st->st_mode))
+                return -EISDIR;
+
+        if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode))
+                return -ENOTTY;
+
+        return 0;
+}
+
+int is_device_node(const char *path) {
+        assert(!isempty(path));
+        return verify_stat_at(AT_FDCWD, path, false, stat_verify_device_node, false);
 }
 
 int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup) {
@@ -260,90 +347,6 @@ int path_is_network_fs(const char *path) {
         return is_network_fs(&s);
 }
 
-int stat_verify_linked(const struct stat *st) {
-        assert(st);
-
-        if (st->st_nlink <= 0)
-                return -EIDRM; /* recognizable error. */
-
-        return 0;
-}
-
-int fd_verify_linked(int fd) {
-        struct stat st;
-
-        assert(fd >= 0);
-
-        if (fstat(fd, &st) < 0)
-                return -errno;
-
-        return stat_verify_linked(&st);
-}
-
-int stat_verify_regular(const struct stat *st) {
-        assert(st);
-
-        /* Checks whether the specified stat() structure refers to a regular file. If not returns an
-         * appropriate error code. */
-
-        if (S_ISDIR(st->st_mode))
-                return -EISDIR;
-
-        if (S_ISLNK(st->st_mode))
-                return -ELOOP;
-
-        if (!S_ISREG(st->st_mode))
-                return -EBADFD;
-
-        return 0;
-}
-
-int fd_verify_regular(int fd) {
-        struct stat st;
-
-        assert(fd >= 0);
-
-        if (fstat(fd, &st) < 0)
-                return -errno;
-
-        return stat_verify_regular(&st);
-}
-
-int verify_regular_at(int dir_fd, const char *path, bool follow) {
-        struct stat st;
-
-        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
-        assert(path);
-
-        if (fstatat(dir_fd, path, &st, (isempty(path) ? AT_EMPTY_PATH : 0) | (follow ? 0 : AT_SYMLINK_NOFOLLOW)) < 0)
-                return -errno;
-
-        return stat_verify_regular(&st);
-}
-
-int stat_verify_directory(const struct stat *st) {
-        assert(st);
-
-        if (S_ISLNK(st->st_mode))
-                return -ELOOP;
-
-        if (!S_ISDIR(st->st_mode))
-                return -ENOTDIR;
-
-        return 0;
-}
-
-int fd_verify_directory(int fd) {
-        struct stat st;
-
-        assert(fd >= 0);
-
-        if (fstat(fd, &st) < 0)
-                return -errno;
-
-        return stat_verify_directory(&st);
-}
-
 int proc_mounted(void) {
         int r;
 
index bab541535728ac4544ae2709ba09e522c2625e58..47445d852a0f83a39427677c4c84a0330accddad 100644 (file)
 #include "siphash24.h"
 #include "time-util.h"
 
+int stat_verify_regular(const struct stat *st);
+int verify_regular_at(int fd, const char *path, bool follow);
+int fd_verify_regular(int fd);
+
+int stat_verify_directory(const struct stat *st);
+int fd_verify_directory(int fd);
+int is_dir_at(int fd, const char *path, bool follow);
+int is_dir(const char *path, bool follow);
+
+int stat_verify_symlink(const struct stat *st);
 int is_symlink(const char *path);
-int is_dir_full(int atfd, const char *fname, bool follow);
-static inline int is_dir(const char *path, bool follow) {
-        return is_dir_full(AT_FDCWD, path, follow);
-}
-static inline int is_dir_fd(int fd) {
-        return is_dir_full(fd, NULL, false);
-}
+
+int stat_verify_linked(const struct stat *st);
+int fd_verify_linked(int fd);
+
+int stat_verify_device_node(const struct stat *st);
 int is_device_node(const char *path);
 
 int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);
@@ -72,16 +80,6 @@ int path_is_network_fs(const char *path);
  */
 #define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b)
 
-int stat_verify_linked(const struct stat *st);
-int fd_verify_linked(int fd);
-
-int stat_verify_regular(const struct stat *st);
-int fd_verify_regular(int fd);
-int verify_regular_at(int dir_fd, const char *path, bool follow);
-
-int stat_verify_directory(const struct stat *st);
-int fd_verify_directory(int fd);
-
 int proc_mounted(void);
 
 bool stat_inode_same(const struct stat *a, const struct stat *b);
index d1736f0aa3f99a4e89ecbb3ede54664ba7b70dee..3601be25fb7b6a4412835e0aa58a060bd1806221 100644 (file)
@@ -1573,7 +1573,7 @@ int verify_timezone(const char *name, int log_level) {
 
         r = fd_verify_regular(fd);
         if (r < 0)
-                return log_full_errno(log_level, r, "Timezone file '%s' is not  a regular file: %m", t);
+                return log_full_errno(log_level, r, "Timezone file '%s' is not a regular file: %m", t);
 
         r = loop_read_exact(fd, buf, 4, false);
         if (r < 0)
index 7f6c1461209eebb181fe9991595babcdeb623747..6afabef4307663f97dcf1fa3dcb15d36c73f839e 100644 (file)
@@ -1066,10 +1066,8 @@ static int process_root_account(int rfd) {
 
         FOREACH_STRING(s, "passwd", "shadow") {
                 r = verify_regular_at(pfd, s, /* follow = */ false);
-                if (IN_SET(r, -EISDIR, -ELOOP, -EBADFD))
-                        return log_error_errno(r, "/etc/%s is not a regular file", s);
                 if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to check whether /etc/%s is a regular file: %m", s);
+                        return log_error_errno(r, "Verification of /etc/%s being regular file failed: %m", s);
 
                 r = should_configure(pfd, s);
                 if (r < 0)
index 273c1d9c4728104f47edafd8297cc0bebec2196c..4df52c8342a1f0a9cd0fe69c7abfc900ec86c315 100644 (file)
@@ -801,7 +801,7 @@ static int context_ensure_layout(Context *c) {
         if (!entry_token_path)
                 return log_oom();
 
-        r = is_dir_full(c->rfd, entry_token_path, /* follow = */ false);
+        r = is_dir_at(c->rfd, entry_token_path, /* follow = */ false);
         if (r < 0 && r != -ENOENT)
                 return log_error_errno(r, "Failed to check if '%s' is a directory: %m", entry_token_path);
         if (r > 0) {