r = xfopenat(dir_fd, filename, "re", 0, &f);
if (r < 0) {
- _cleanup_close_ int dfd = -1, sk = -1;
- union sockaddr_union sa;
+ _cleanup_close_ int sk = -1;
/* ENXIO is what Linux returns if we open a node that is an AF_UNIX socket */
if (r != -ENXIO)
if (offset != UINT64_MAX)
return -ENXIO;
- if (dir_fd == AT_FDCWD)
- r = sockaddr_un_set_path(&sa.un, filename);
- else {
- /* If we shall operate relative to some directory, then let's use O_PATH first to
- * open the socket inode, and then connect to it via /proc/self/fd/. We have to do
- * this since there's not connectat() that takes a directory fd as first arg. */
-
- dfd = openat(dir_fd, filename, O_PATH|O_CLOEXEC);
- if (dfd < 0)
- return -errno;
-
- r = sockaddr_un_set_path(&sa.un, FORMAT_PROC_FD_PATH(dfd));
- }
- if (r < 0)
- return r;
-
sk = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
if (sk < 0)
return -errno;
return -errno;
}
- if (connect(sk, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
- return errno == ENOTSOCK ? -ENXIO : -errno; /* propagate original error if this is
- * not a socket after all */
+ r = connect_unix_path(sk, dir_fd, filename);
+ if (IN_SET(r, -ENOTSOCK, -EINVAL)) /* propagate original error if this is not a socket after all */
+ return -ENXIO;
+ if (r < 0)
+ return r;
if (shutdown(sk, SHUT_WR) < 0)
return -errno;
_cleanup_close_ int listener = -1;
_cleanup_free_ char *data = NULL, *clientname = NULL;
union sockaddr_union sa;
- const char *j;
+ const char *j, *jj;
size_t size;
pid_t pid;
int r;
assert_se(bind(listener, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0);
assert_se(listen(listener, 1) >= 0);
+ /* Make sure the socket doesn't fit into a struct sockaddr_un, but we can still access it */
+ jj = strjoina(z, "/a_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_patha_very_long_path");
+ assert_se(strlen(jj) > sizeof_field(struct sockaddr_un, sun_path));
+ assert_se(rename(j, jj) >= 0);
+
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
_exit(EXIT_SUCCESS);
}
- assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
- assert_se(read_full_file_full(AT_FDCWD, j, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
+ assert_se(read_full_file_full(AT_FDCWD, jj, UINT64_MAX, SIZE_MAX, 0, NULL, &data, &size) == -ENXIO);
+ assert_se(read_full_file_full(AT_FDCWD, jj, UINT64_MAX, SIZE_MAX, READ_FULL_FILE_CONNECT_SOCKET, clientname, &data, &size) >= 0);
assert_se(size == strlen(TEST_STR));
assert_se(streq(data, TEST_STR));