#include <sys/socket.h>
#include "macro.h"
+#include "format-util.h"
+#include "process-util.h"
#include "stdio-util.h"
/* maximum length of fdname */
return dir_fd == AT_FDCWD ? true : path_is_root_at(dir_fd, NULL);
}
-/* The maximum length a buffer for a /proc/self/fd/<fd> path needs */
+/* The maximum length a buffer for a /proc/<pid>/fd/<fd> path needs. We intentionally don't use /proc/self/fd
+ * as these paths might be read by other programs (for example when mounting file descriptors the source path
+ * ends up in /proc/mounts and related files) for which /proc/self/fd will be interpreted differently than
+ * /proc/<pid>/fd. */
#define PROC_FD_PATH_MAX \
- (STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int))
+ (STRLEN("/proc//fd/") + DECIMAL_STR_MAX(pid_t) + DECIMAL_STR_MAX(int))
static inline char *format_proc_fd_path(char buf[static PROC_FD_PATH_MAX], int fd) {
assert(buf);
assert(fd >= 0);
- assert_se(snprintf_ok(buf, PROC_FD_PATH_MAX, "/proc/self/fd/%i", fd));
+ assert_se(snprintf_ok(buf, PROC_FD_PATH_MAX, "/proc/" PID_FMT "/fd/%i", getpid_cached(), fd));
return buf;
}
}
TEST(format_proc_fd_path) {
- assert_se(streq_ptr(FORMAT_PROC_FD_PATH(0), "/proc/self/fd/0"));
- assert_se(streq_ptr(FORMAT_PROC_FD_PATH(1), "/proc/self/fd/1"));
- assert_se(streq_ptr(FORMAT_PROC_FD_PATH(2), "/proc/self/fd/2"));
- assert_se(streq_ptr(FORMAT_PROC_FD_PATH(3), "/proc/self/fd/3"));
- assert_se(streq_ptr(FORMAT_PROC_FD_PATH(2147483647), "/proc/self/fd/2147483647"));
+ _cleanup_free_ char *expected = NULL;
+
+ for (int i = 0; i < 4; i++) {
+ assert_se(asprintf(&expected, "/proc/" PID_FMT "/fd/%i", getpid_cached(), i) >= 0);
+ assert_se(streq_ptr(FORMAT_PROC_FD_PATH(i), expected));
+ expected = mfree(expected);
+ }
+
+ assert_se(asprintf(&expected, "/proc/" PID_FMT "/fd/2147483647", getpid_cached()) >= 0);
+ assert_se(streq_ptr(FORMAT_PROC_FD_PATH(2147483647), expected));
}
TEST(fd_reopen) {