fd-util: introduce proc_fd_enoent_errno helper

Currently, if proc_mounted() != 0, some functions
propagate -ENOENT while others return -EBADF.
Let's make things consistent, by introducing
a static inline helper responsible for finding out
the appropriate errno.
This commit is contained in:
Mike Yuan
2024-05-22 00:50:44 +08:00
parent 69baf0cb91
commit d19b3c5d99
4 changed files with 28 additions and 44 deletions
+18 -19
View File
@@ -617,16 +617,8 @@ int fd_get_path(int fd, char **ret) {
return safe_getcwd(ret);
r = readlink_malloc(FORMAT_PROC_FD_PATH(fd), ret);
if (r == -ENOENT) {
/* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's make
* things debuggable and distinguish the two. */
if (proc_mounted() == 0)
return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
}
if (r == -ENOENT)
return proc_fd_enoent_errno();
return r;
}
@@ -823,8 +815,6 @@ finish:
}
int fd_reopen(int fd, int flags) {
int r;
assert(fd >= 0 || fd == AT_FDCWD);
assert(!FLAGS_SET(flags, O_CREAT));
@@ -860,13 +850,7 @@ int fd_reopen(int fd, int flags) {
if (errno != ENOENT)
return -errno;
r = proc_mounted();
if (r == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return r > 0 ? -EBADF : -ENOENT; /* If /proc/ is definitely around then this means the fd is
* not valid, otherwise let's propagate the original
* error */
return proc_fd_enoent_errno();
}
return new_fd;
@@ -1136,3 +1120,18 @@ char *format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid,
assert_se(snprintf_ok(buf, PROC_PID_FD_PATH_MAX, "/proc/" PID_FMT "/fd/%i", pid == 0 ? getpid_cached() : pid, fd));
return buf;
}
int proc_fd_enoent_errno(void) {
int r;
/* When ENOENT is returned during the use of FORMAT_PROC_FD_PATH, it can mean two things:
* that the fd does not exist or that /proc/ is not mounted.
* Let's make things debuggable and figure out the most appropriate errno. */
r = proc_mounted();
if (r == 0)
return -ENOSYS; /* /proc/ is not available or not set up properly, we're most likely
in some chroot environment. */
return r > 0 ? -EBADF : -ENOENT; /* If /proc/ is definitely around then this means the fd is
not valid, otherwise let's propagate the original ENOENT. */
}
+2
View File
@@ -161,6 +161,8 @@ char *format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid,
#define FORMAT_PROC_PID_FD_PATH(pid, fd) \
format_proc_pid_fd_path((char[PROC_PID_FD_PATH_MAX]) {}, (pid), (fd))
int proc_fd_enoent_errno(void);
const char *accmode_to_string(int flags);
/* Like ASSERT_PTR, but for fds */
+3 -16
View File
@@ -313,10 +313,7 @@ int fchmod_opath(int fd, mode_t m) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS; /* if we have no /proc/, the concept is not implementable */
return -ENOENT;
return proc_fd_enoent_errno();
}
return 0;
@@ -339,10 +336,7 @@ int futimens_opath(int fd, const struct timespec ts[2]) {
if (errno != ENOENT)
return -errno;
if (proc_mounted() == 0)
return -ENOSYS;
return -ENOENT;
return proc_fd_enoent_errno();
}
return 0;
@@ -685,14 +679,7 @@ int access_fd(int fd, int mode) {
if (errno != ENOENT)
return -errno;
/* ENOENT can mean two things: that the fd does not exist or that /proc is not mounted. Let's
* make things debuggable and distinguish the two. */
if (proc_mounted() == 0)
return -ENOSYS; /* /proc is not available or not set up properly, we're most likely in some chroot
* environment. */
return -EBADF; /* The directory exists, hence it's the fd that doesn't. */
return proc_fd_enoent_errno();
}
return 0;
+5 -9
View File
@@ -42,7 +42,10 @@ bool inotify_event_next(
}
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
int wd, r;
int wd;
assert(fd >= 0);
assert(what >= 0);
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
wd = inotify_add_watch(fd, FORMAT_PROC_FD_PATH(what), mask);
@@ -50,14 +53,7 @@ int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
if (errno != ENOENT)
return -errno;
/* Didn't work with ENOENT? If so, then either /proc/ isn't mounted, or the fd is bad */
r = proc_mounted();
if (r == 0)
return -ENOSYS;
if (r > 0)
return -EBADF;
return -ENOENT; /* OK, no clue, let's propagate the original error */
return proc_fd_enoent_errno();
}
return wd;