| commit e368b12f6c16b6888dda99ba641e999b9c9643c8 |
| Author: Florian Weimer <fweimer@redhat.com> |
| Date: Mon Jan 17 10:21:34 2022 +0100 |
| |
| socket: Add the __sockaddr_un_set function |
| |
| Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> |
| |
| # Conflicts: |
| # socket/Makefile |
| |
| diff --git a/include/sys/un.h b/include/sys/un.h |
| index bdbee999806930f4..152afd9fc7426d8b 100644 |
| |
| |
| @@ -1 +1,13 @@ |
| #include <socket/sys/un.h> |
| + |
| +#ifndef _ISOMAC |
| + |
| +/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME. |
| + Return 0 on success or -1 on failure (due to overlong PATHNAME). |
| + The caller should always use sizeof (struct sockaddr_un) as the |
| + socket address length, disregaring the length of PATHNAME. |
| + Only concrete (non-abstract) pathnames are supported. */ |
| +int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) |
| + attribute_hidden; |
| + |
| +#endif /* _ISOMAC */ |
| diff --git a/socket/Makefile b/socket/Makefile |
| index b41eb071507a6271..8975a65c2aabbfbc 100644 |
| |
| |
| @@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \ |
| routines := accept bind connect getpeername getsockname getsockopt \ |
| listen recv recvfrom recvmsg send sendmsg sendto \ |
| setsockopt shutdown socket socketpair isfdtype opensock \ |
| - sockatmark accept4 recvmmsg sendmmsg |
| + sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set |
| |
| tests := tst-accept4 |
| |
| +tests-internal := \ |
| + tst-sockaddr_un_set \ |
| + # tests-internal |
| + |
| aux := sa_len |
| |
| include ../Rules |
| diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c |
| new file mode 100644 |
| index 0000000000000000..0bd40dc34e3d7efc |
| |
| |
| @@ -0,0 +1,41 @@ |
| +/* Set the sun_path member of struct sockaddr_un. |
| + Copyright (C) 2022 Free Software Foundation, Inc. |
| + This file is part of the GNU C Library. |
| + |
| + The GNU C Library is free software; you can redistribute it and/or |
| + modify it under the terms of the GNU Lesser General Public |
| + License as published by the Free Software Foundation; either |
| + version 2.1 of the License, or (at your option) any later version. |
| + |
| + The GNU C Library is distributed in the hope that it will be useful, |
| + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + Lesser General Public License for more details. |
| + |
| + You should have received a copy of the GNU Lesser General Public |
| + License along with the GNU C Library; if not, see |
| + <https://www.gnu.org/licenses/>. */ |
| + |
| +#include <errno.h> |
| +#include <string.h> |
| +#include <sys/socket.h> |
| +#include <sys/un.h> |
| + |
| +int |
| +__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) |
| +{ |
| + size_t name_length = strlen (pathname); |
| + |
| + /* The kernel supports names of exactly sizeof (addr->sun_path) |
| + bytes, without a null terminator, but userspace does not; see the |
| + SUN_LEN macro. */ |
| + if (name_length >= sizeof (addr->sun_path)) |
| + { |
| + __set_errno (EINVAL); /* Error code used by the kernel. */ |
| + return -1; |
| + } |
| + |
| + addr->sun_family = AF_UNIX; |
| + memcpy (addr->sun_path, pathname, name_length + 1); |
| + return 0; |
| +} |
| diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c |
| new file mode 100644 |
| index 0000000000000000..29c2a81afda81b5e |
| |
| |
| @@ -0,0 +1,62 @@ |
| +/* Test the __sockaddr_un_set function. |
| + Copyright (C) 2022 Free Software Foundation, Inc. |
| + This file is part of the GNU C Library. |
| + |
| + The GNU C Library is free software; you can redistribute it and/or |
| + modify it under the terms of the GNU Lesser General Public |
| + License as published by the Free Software Foundation; either |
| + version 2.1 of the License, or (at your option) any later version. |
| + |
| + The GNU C Library is distributed in the hope that it will be useful, |
| + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + Lesser General Public License for more details. |
| + |
| + You should have received a copy of the GNU Lesser General Public |
| + License along with the GNU C Library; if not, see |
| + <https://www.gnu.org/licenses/>. */ |
| + |
| +/* Re-compile the function because the version in libc is not |
| + exported. */ |
| +#include "sockaddr_un_set.c" |
| + |
| +#include <support/check.h> |
| + |
| +static int |
| +do_test (void) |
| +{ |
| + struct sockaddr_un sun; |
| + |
| + memset (&sun, 0xcc, sizeof (sun)); |
| + __sockaddr_un_set (&sun, ""); |
| + TEST_COMPARE (sun.sun_family, AF_UNIX); |
| + TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0); |
| + |
| + memset (&sun, 0xcc, sizeof (sun)); |
| + TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0); |
| + TEST_COMPARE_STRING (sun.sun_path, "/example"); |
| + |
| + { |
| + char pathname[108]; /* Length of sun_path (ABI constant). */ |
| + memset (pathname, 'x', sizeof (pathname)); |
| + pathname[sizeof (pathname) - 1] = '\0'; |
| + memset (&sun, 0xcc, sizeof (sun)); |
| + TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0); |
| + TEST_COMPARE (sun.sun_family, AF_UNIX); |
| + TEST_COMPARE_STRING (sun.sun_path, pathname); |
| + } |
| + |
| + { |
| + char pathname[109]; |
| + memset (pathname, 'x', sizeof (pathname)); |
| + pathname[sizeof (pathname) - 1] = '\0'; |
| + memset (&sun, 0xcc, sizeof (sun)); |
| + errno = 0; |
| + TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1); |
| + TEST_COMPARE (errno, EINVAL); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +#include <support/test-driver.c> |